Hud 敌兵布阵 --线段树的插点问线
生活随笔
收集整理的這篇文章主要介紹了
Hud 敌兵布阵 --线段树的插点问线
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
???? 每個樹存放的事左右端點的的總和,然后再遞歸往下分成更小的區間,根據著2*t是下一層節點的節點端點是(left,left+right)/2);2*t+1是右節點的區間是(left+right)/2+1,right);
而更新的時候就是把點當成是(x,x)這樣的區間然后去尋找它所在區間的葉子節點,然后回溯把所有祖先的區間都更新了,然后即使查找的了,當你查找的區間是(l,r)時,你先是從最大的區間開始去查找也就是從節點等于一開始查找看是否與所求的區間相等,不等時有三種可能就是在左右節點或者是左右節點的區間各有一半,然后就分開討論。
?
#include<stdio.h> #include<string.h> #define mid(x,y) (x+y)/2 int v,b; int a[500005],ans,cnt; struct app {int left,right;int sum; }tree[500000]; void build_tree(int left,int right,int t) //建樹,l,r是區間的左右端點數,t是每次從從1開始然后繁衍兒子 {int x;tree[t].left=left;tree[t].right=right;tree[t].sum=0;if(left==right){ //當它已經是葉子了不能在繁衍了就開始回溯讓它的所有祖先都加上兒子(敵營)的人數while(t!=0) {tree[t].sum+=a[left];t/=2; //下一個祖先}return ;}x=mid(left,right);build_tree(left,x,2*t); //對每個區間不斷的遞歸讓它們能不斷分離下去,注意哦,這里是不斷找出每個區間的左區間,直到找完了再開始從頭找右節點 build_tree(x+1,right,2*t+1); }void updata_tree(int left,int right,int t) //更新線段樹,先找到所更新點的葉子,然后再把此點和所有的祖先區間都更新 {if(tree[t].left==left&&tree[t].right==right){while(t!=0){tree[t].sum+=cnt;t/=2;}return ;}int x=mid(tree[t].left,tree[t].right);if(x>=right) // 分到的點可以鎖定在右邊的區間所以,關鍵在2*t著才是代表在右邊updata_tree(left,right,2*t);else if(x+1<=left)updata_tree(left,right,2*t+1);else{updata_tree(left,x,2*t);updata_tree(x+1,right,2*t+1);} }void query_tree(int left,int right,int t) //查找區間如果是在區間里面的就直接把和加上,如果是是在左右區間的中間那就分開加直到你加到你查找的區間被包含在現有的區間內,就結束了然后把你所經歷的區間的值加起來就是結果了 {if(tree[t].left==left&&tree[t].right==right){ans+=tree[t].sum;return ;}int x=mid(tree[t].left,tree[t].right);if(x>=right){query_tree(left,right,2*t);}else if(x+1<=left)query_tree(left,right,2*t+1);else{query_tree(left,x,2*t);query_tree(x+1,right,2*t+1);} }int main() {int t,n,i,j;scanf("%d",&t);for(i=1;i<=t;i++){printf("Case %d:\n",i);scanf("%d",&n);memset(a,0,sizeof(a));for(j=1;j<=n;j++)scanf("%d",&a[j]);build_tree(1,n,1);char sh[10];while(1){scanf("%s",sh);if(sh[0]=='E')break;if(sh[0]=='A'){scanf("%d%d",&v,&cnt);updata_tree(v,v,1);}if(sh[0]=='Q'){scanf("%d%d",&v,&b);ans=0;query_tree(v,b,1);printf("%d\n",ans);}if(sh[0]=='S'){scanf("%d%d",&v,&cnt);cnt=-cnt;updata_tree(v,v,1);}}}return 0; }總結
以上是生活随笔為你收集整理的Hud 敌兵布阵 --线段树的插点问线的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串周期--hdu 3746 Cycl
- 下一篇: 欧拉函数的相关应用 noj欧拉函数求