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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  好題。我做了很久,學了大牛們的區間搬移。主要的代碼都有注釋。

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 999999999 #define key_value ch[ch[root][1]][0] using namespace std; const int MAXN = 200010; int pre[MAXN],lazy[MAXN],siz[MAXN],ch[MAXN][2],s[MAXN],key[MAXN],tot1,tot2,root,ans[MAXN]; int n,a[MAXN],rev[MAXN];//rev表示旋轉 lazy標記增加的量 /****************************/ void Treavel(int x) {if(x){Treavel(ch[x][0]);printf("結點%2d:左兒子 %2d 右兒子 %2d 父結點 %2d size=%2d,key=%2d lazy=%2d rev=%2d ans=%2d\n",x,ch[x][0],ch[x][1],pre[x],siz[x],key[x],lazy[x],rev[x],ans[x]);Treavel(ch[x][1]);} } void debug() {printf("root:%d\n",root);Treavel(root); } /****************************/ void Newnode(int &rt,int pa,int k) {if(tot2)rt = s[--tot2];elsert = ++tot1;pre[rt] = pa;key[rt] = k;lazy[rt] = 0;siz[rt] = 1;rev[rt] = 0;ans[rt] = k;ch[rt][0] = ch[rt][1] = 0; } void pushup(int rt) {siz[rt] = siz[ch[rt][0]] + siz[ch[rt][1]] + 1;ans[rt] = key[rt];if(ch[rt][0]) //因為是minans[rt] = min(ans[rt],ans[ch[rt][0]]);if(ch[rt][1]) ans[rt] = min(ans[rt],ans[ch[rt][1]]); } void pushdown(int rt) {if(rev[rt]){rev[ch[rt][0]] ^= 1;rev[ch[rt][1]] ^= 1;swap(ch[rt][0],ch[rt][1]);rev[rt] = 0;}if(lazy[rt]){lazy[ch[rt][0]] += lazy[rt];lazy[ch[rt][1]] += lazy[rt];key[ch[rt][0]] += lazy[rt];key[ch[rt][1]] += lazy[rt];ans[ch[rt][0]] += lazy[rt];ans[ch[rt][1]] += lazy[rt];lazy[rt] = 0;} } void build(int &rt,int l,int r,int pa) {if(l > r)return ;int m = (l+r)/2;Newnode(rt,pa,a[m]);build(ch[rt][0],l,m-1,rt);build(ch[rt][1],m+1,r,rt);pushup(rt); } void Init() {tot1 = tot2 = root = 0;siz[root] = pre[root] = lazy[root] = key[root] = rev[root] = 0;ans[root] = INF;ch[root][0] = ch[root][1] = 0;Newnode(root,0,-1);Newnode(ch[root][1],root,-1);build(key_value,1,n,ch[root][1]);pushup(ch[root][1]);pushup(root); } //先pushdown將lazy壓下去 void Rotate(int rt,int kind) {pushdown(pre[rt]);pushdown(rt);int y = pre[rt];ch[y][!kind] = ch[rt][kind];pre[ch[rt][kind]] = y;if(pre[y]){ch[pre[y]][ch[pre[y]][1]==y] = rt;}pre[rt] = pre[y];ch[rt][kind] = y;pre[y] = rt;pushup(y);pushup(rt); } //先pushdown將lazy壓下去 void splay(int rt,int goal) {pushdown(rt);while(pre[rt] != goal){if(pre[pre[rt]] == goal){pushdown(pre[rt]);pushdown(rt);Rotate(rt,ch[pre[rt]][0]==rt);}else {pushdown(pre[pre[rt]]);pushdown(pre[rt]);pushdown(rt);int y = pre[rt];int kind = ch[pre[y]][0]==y;if(ch[y][kind] == rt){Rotate(rt,!kind);Rotate(rt,kind);}else {Rotate(y,kind);Rotate(rt,kind);}}}pushup(rt);if(goal == 0)root = rt;} int Get_kth(int rt,int k) {pushdown(rt);int t = siz[ch[rt][0]] + 1;if(t == k)return rt;else if(t > k){return Get_kth(ch[rt][0],k);}else {return Get_kth(ch[rt][1],k-t);}pushup(rt); } void add(int x,int y,int z) {splay(Get_kth(root,x),0);splay(Get_kth(root,y+2),root);lazy[key_value] += z;key[key_value] += z;ans[key_value] += z;pushup(ch[root][1]);pushup(root);// } int Get_min(int rt) {pushdown(rt);while(ch[rt][0]){rt = ch[rt][0];pushdown(rt);}return rt; } int Get_max(int rt) {pushdown(rt);while(ch[rt][1]){rt = ch[rt][1];pushdown(rt);}return rt; } int query(int x,int y) {splay(Get_kth(root,x),0);splay(Get_kth(root,y+2),root);return ans[key_value]; } void Del(int x) {splay(Get_kth(root,x),0);splay(Get_kth(root,x+2),root);pre[key_value] = 0;key_value = 0;pushup(ch[root][1]);pushup(root); } void Insert(int x,int y) {splay(Get_kth(root,x+1),0);splay(Get_kth(root,x+2),root);Newnode(key_value,ch[root][1],y);pushup(ch[root][1]);pushup(root); } void Reverse(int x,int y) {splay(Get_kth(root,x),0);splay(Get_kth(root,y+2),root);rev[key_value] ^= 1;pushup(ch[root][1]);pushup(root); } void Revolve(int l,int r,int t) {//區間平移其實就是把區間[l,c-1],[c,r]中的[c,r]放到[l,c-1]前int len = r - l + 1;//取modt = (t%len + len)%len;if(!t)return ;int c = r - t + 1;splay(Get_kth(root,c),0);splay(Get_kth(root,r+2),root);int tmp = key_value;//這里的是[c,r]的區間key_value = 0;pushup(ch[root][1]);pushup(root);//注意這兩步 這里把key_value取0 這樣主要為了取走[c,r],所以要更新splay(Get_kth(root,l),0);splay(Get_kth(root,l+1),root);key_value = tmp;pre[key_value] = ch[root][1];pushup(ch[root][1]);pushup(root); } int main() {int i,j;while(~scanf("%d",&n)){for(i=1; i<=n; i++){scanf("%d",&a[i]);}Init();int q;scanf("%d",&q);char work[10];//debug();//cout<<"test: "<<endl;while(q--){scanf("%s",work);if(work[0] == 'A'){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z);//debug(); }else if(work[0] == 'M'){int x,y;scanf("%d%d",&x,&y);printf("%d\n",query(x,y));}else if(work[0] == 'D'){int x;scanf("%d",&x);Del(x);//debug(); }else if(work[0] == 'I'){int x,y;scanf("%d%d",&x,&y);Insert(x,y);//debug(); }else if(strcmp(work,"REVERSE") == 0){int x,y;scanf("%d%d",&x,&y);Reverse(x,y);//debug(); }else if(strcmp(work,"REVOLVE") == 0){int x,y,ft;scanf("%d%d%d",&x,&y,&ft);Revolve(x,y,ft);//debug(); }}} }

?

轉載于:https://www.cnblogs.com/sweat123/p/5140362.html

總結

以上是生活随笔為你收集整理的poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)的全部內容,希望文章能夠幫你解決所遇到的問題。

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