日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hud 敌兵布阵 --线段树的插点问线

發布時間:2025/3/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 敌兵布阵 --线段树的插点问线的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。