数据结构---各种树模板

1:Trie 字典树

字典树

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

它有3个基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 每个节点的所有子节点包含的字符都不相同。

详细应用见  http://blog.csdn.net/metalseed/article/details/7953262
  1. #include <iostream>    
  2. using namespace std;    
  3. #define MAX 26 //字符集大小    
  4.     
  5. typedef struct TrieNode {    
  6.     int nCount;    
  7.     struct TrieNode *next[MAX];    
  8. }TrieNode;    
  9.     
  10. TrieNode Memory[1000000];    
  11. int allocp =0;    
  12.     
  13. TrieNode *CreateTrieNode() {    
  14.     int i;    
  15.     TrieNode *p;    
  16.     p = &Memory[allocp++];    
  17.     p->nCount = 1;    
  18.     for(i =0 ; i < MAX ; i++) {    
  19.         p->next[i] = NULL;    
  20.     }    
  21.     return p;    
  22. }    
  23.     
  24. void InsertTrie(TrieNode * &pRoot , char*s) {    
  25.     int i, k;    
  26.     TrieNode *p;    
  27.     if(!(p = pRoot)) {    
  28.         p = pRoot = CreateTrieNode();    
  29.     }    
  30.     i = 0;    
  31.     while(s[i]) {    
  32.         k = s[i++] - 'a';    
  33.         if(p->next[k])    
  34.             p->next[k]->nCount++;    
  35.         else    
  36.             p->next[k] = CreateTrieNode();    
  37.         p = p->next[k];    
  38.     }    
  39. }    
  40. /*查询该前缀出现次数*/    
  41. /*若查询该词出现次数  
  42.   则所有的count初始化为0  
  43.   并去除所有对count的操作  
  44.   只在每次InsertTrie末尾加 p->nCount++;   
  45. */     
  46. int SearchTrie(TrieNode * &pRoot , char*s) {    
  47.     TrieNode *p;    
  48.     int i , k;    
  49.     if(!(p = pRoot)) {    
  50.         return 0;    
  51.     }    
  52.     i = 0;    
  53.     while(s[i]) {    
  54.         k = s[i++] -'a';    
  55.         if(p->next[k] == NULL) return 0;    
  56.         p = p->next[k];    
  57.     }    
  58.     return p->nCount;    
  59. }    
  60.     
  61. int main()    
  62. {    
  63.     TrieNode *ROOT = NULL;    
  64.     InsertTrie(ROOT,"see");    
  65.     InsertTrie(ROOT,"seeda");    
  66.     InsertTrie(ROOT,"seedb");    
  67.     InsertTrie(ROOT,"seeda");    
  68.     cout<<SearchTrie(ROOT,"seeda")<<endl;    
  69.     cout<<SearchTrie(ROOT,"seedb")<<endl;    
  70.     cout<<SearchTrie(ROOT,"see")<<endl;    
  71.     return 0;    
  72. }    




3:BIT 树状数组

1、概述

树状数组(binary indexed tree),是一种设计新颖的数组结构,它能够高效地获取数组中连续n个数的和。概括说,树状数组通常用于解决以下问题:数组{a}中的元素可能不断地被修改,怎样才能快速地获取连续几个数的和?

2、树状数组基本操作

传统数组(共n个元素)的元素修改和连续元素求和的复杂度分别为O(1)和O(n)。树状数组通过将线性结构转换成伪树状结构(线性结构只能逐个扫描元素,而树状结构可以实现跳跃式扫描),使得修改和求和复杂度均为O(lgn),大大提高了整体效率。

详见 : http://blog.csdn.net/metalseed/article/details/7984075   (含2D模板)
  1. #include<iostream>    
  2. #include<algorithm>    
  3. using namespace std;    
  4.     
  5.     
  6.     
  7. /* 1D */       
  8. const int maxn = 10000;      
  9. int tree[maxn],maxID = 0xff/*数组长度,由题定,建树用update*/;      
  10.       
  11. inline void init()      
  12. {      
  13.     memset(tree,0,sizeof(tree));      
  14. }      
  15.       
  16. inline int read(int idx){ /*求前idx项和*/      
  17.     int sum = 0;      
  18.     while (idx > 0){      
  19.         sum += tree[idx];      
  20.         idx -= (idx & -idx);      
  21.     }      
  22.     return sum;      
  23. }      
  24.     
  25. inline int readSingle(int idx){ /*求idx单点值*/    
  26.     int sum = tree[idx];    
  27.     if (idx > 0){    
  28.         int z = idx - (idx & -idx);    
  29.         idx--;     
  30.         while (idx != z){    
  31.             sum -= tree[idx];     
  32.             idx -= (idx & -idx);    
  33.         }    
  34.     }    
  35.     return sum;    
  36. }    
  37.     
  38. inline void update(int idx ,int val){  /*给idx位置叠加val,叠加!*/     
  39.     while (idx <= maxID){      
  40.         tree[idx] += val;      
  41.         idx += (idx & -idx);      
  42.     }      
  43. }     
  44.     
  45.     
  46.     
  47. int main()    
  48. {    
  49.     cout << read(10) << endl;    
  50.     for(int i = 0; i< 10; ++i)    
  51.     {    
  52.         update(i+1,i+1);    
  53.     }    
  54.     update(4,999);    
  55.     cout << read(1) << endl;    
  56.     cout << read(3) << endl;    
  57.         
  58.     cout << readSingle(4) << endl;    
  59.     return 0;    
  60. }    

4:Segment Tree 线段树


成段加C  区间求和

  1. #include <cstdio>    
  2. #include <algorithm>    
  3. using namespace std;    
  4.      
  5. #define lson l , m , rt << 1    
  6. #define rson m + 1 , r , rt << 1 | 1    
  7. #define LL long long    
  8. const int maxn = 111111;    
  9.   
  10. /* Node Begin */  
  11. LL add[maxn<<2];    
  12. LL sum[maxn<<2];    
  13. /* Node End */  
  14.   
  15. void PushUp(int rt) {    
  16.     sum[rt] = sum[rt<<1] + sum[rt<<1|1];    
  17. }    
  18. void PushDown(int rt,int m) {    
  19.     if (add[rt]) {    
  20.         add[rt<<1] += add[rt];    
  21.         add[rt<<1|1] += add[rt];    
  22.         sum[rt<<1] += add[rt] * (m - (m >> 1));    
  23.         sum[rt<<1|1] += add[rt] * (m >> 1);    
  24.         add[rt] = 0;    
  25.     }    
  26. }    
  27. void build(int l,int r,int rt) {    
  28.     add[rt] = 0;    
  29.     if (l == r) {    
  30.         scanf("%lld",&sum[rt]);    
  31.         return ;    
  32.     }    
  33.     int m = (l + r) >> 1;    
  34.     build(lson);    
  35.     build(rson);    
  36.     PushUp(rt);    
  37. }    
  38. void update(int L,int R,int c,int l,int r,int rt) {    
  39.     if (L <= l && r <= R) {    
  40.         add[rt] += c;    
  41.         sum[rt] += (LL)c * (r - l + 1);    
  42.         return ;    
  43.     }    
  44.     PushDown(rt , r - l + 1);    
  45.     int m = (l + r) >> 1;    
  46.     if (L <= m) update(L , R , c , lson);    
  47.     if (m < R) update(L , R , c , rson);    
  48.     PushUp(rt);    
  49. }    
  50. LL query(int L,int R,int l,int r,int rt) {    
  51.     if (L <= l && r <= R) {    
  52.         return sum[rt];    
  53.     }    
  54.     PushDown(rt , r - l + 1);    
  55.     int m = (l + r) >> 1;    
  56.     LL ret = 0;    
  57.     if (L <= m) ret += query(L , R , lson);    
  58.     if (m < R) ret += query(L , R , rson);    
  59.     return ret;    
  60. }    
  61. int main() {    
  62.     int N , Q;    
  63.     scanf("%d%d",&N,&Q);    
  64.     build(1 , N , 1);    
  65.     while (Q --) {    
  66.         char op[2];    
  67.         int a , b , c;    
  68.         scanf("%s",op);    
  69.         if (op[0] == 'Q')   
  70.         {    
  71.             scanf("%d%d",&a,&b);    
  72.             printf("%lld\n",query(a , b , 1 , N , 1));    
  73.         }   
  74.         else   
  75.         {    
  76.             scanf("%d%d%d",&a,&b,&c);    
  77.             update(a , b , c , 1 , N , 1);    
  78.         }    
  79.     }    
  80.     return 0;    
  81. }    





5:SBT 二叉平衡检索树

http://acm.hdu.edu.cn/showproblem.php?pid=4006


  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #define MAX 1000010  
  4.   
  5.   
  6. int n,m;  
  7. struct SBT {  
  8.   
  9.     int left,right,size,key;  
  10.     void Init() {  
  11.   
  12.         left = right = 0;  
  13.         size = 1;  
  14.     }  
  15. }a[MAX];  
  16. int tot,root;  
  17.   
  18.   
  19. void left_rotate(int &t) {  
  20.   
  21.     int k = a[t].right;  
  22.     a[t].right = a[k].left;  
  23.     a[k].left = t;  
  24.     a[k].size = a[t].size;  
  25.     a[t].size = a[a[t].left].size + a[a[t].right].size + 1;  
  26.     t = k;  
  27. }  
  28. void right_rotate(int &t) {  
  29.   
  30.     int k = a[t].left;  
  31.     a[t].left = a[k].right;  
  32.     a[k].right = t;  
  33.     a[k].size = a[t].size;  
  34.     a[t].size = a[a[t].left].size + a[a[t].right].size + 1;  
  35.     t = k;  
  36. }  
  37. void maintain(int &t,int flag) {  
  38.   
  39.     if (flag == 0) {  
  40.   
  41.         if (a[a[a[t].left].left].size > a[a[t].right].size)   
  42.             right_rotate(t);  
  43.         else if (a[a[a[t].left].right].size > a[a[t].right].size)  
  44.             left_rotate(a[t].left),right_rotate(t);  
  45.         else return;  
  46.     }  
  47.     else {  
  48.   
  49.         if (a[a[a[t].right].right].size > a[a[t].left].size)  
  50.             left_rotate(t);  
  51.         else if (a[a[a[t].right].left].size > a[a[t].left].size)  
  52.             right_rotate(a[t].right),left_rotate(t);  
  53.         else return;  
  54.     }  
  55.     maintain(a[t].left,0);  
  56.     maintain(a[t].right,1);  
  57.     maintain(t,0);  
  58.     maintain(t,1);  
  59. }  
  60. void insert(int &t,int v) {  
  61.   
  62.     if (t == 0)  
  63.         t = ++tot,a[t].Init(),a[t].key = v;  
  64.     else {  
  65.   
  66.         a[t].size++;  
  67.         if (v < a[t].key)  
  68.             insert(a[t].left,v);  
  69.         else insert(a[t].right,v);  
  70.         maintain(t,v>=a[t].key);  
  71.     }  
  72. }  
  73. int del(int &t,int v) {  
  74.   
  75.     if (!t) return 0;  
  76.     a[t].size--;  
  77.   
  78.     if (v == a[t].key || v < a[t].key && !a[t].left  
  79.         || v > a[t].key && !a[t].right) {  
  80.   
  81.         if (a[t].left && a[t].right) {  
  82.   
  83.             int p = del(a[t].left,v+1);  
  84.             a[t].key = a[p].key;  
  85.             return p;  
  86.         }  
  87.         else {  
  88.   
  89.             int p = t;  
  90.             t = a[t].left + a[t].right;  
  91.             return p;  
  92.         }  
  93.     }  
  94.     else return del(v<a[t].key?a[t].left:a[t].right,v);  
  95. }  
  96. int find(int t,int k) {  
  97.   
  98.     if (k <= a[a[t].left].size)  
  99.         return find(a[t].left,k);  
  100.     if (k > a[a[t].left].size + 1)  
  101.         return find(a[t].right,k-a[a[t].left].size-1);  
  102.     return a[t].key;  
  103. }  
  104.   
  105.   
  106. int main()  
  107. {  
  108.     int i,j,k;  
  109.   
  110.   
  111.     while (scanf("%d%d",&n,&m) != EOF) {  
  112.   
  113.         tot = root = 0;  
  114.         char ope[10];  
  115.         while (n--) {  
  116.   
  117.             scanf("%s",ope);  
  118.             if (ope[0] == 'I') {  
  119.   
  120.                 scanf("%d",&k);  
  121.                 insert(root,k);  
  122.             }  
  123.             else printf("%d\n",find(root,a[root].size+1-m));  
  124.         }  
  125.     }  
  126. }  


6:Splay 伸展树

  1. /* 
  2. 题意:有N个数字围成一个圈,有M个操作,操作类型有六种: 
  3. (1)“add x",从当前指针位置开始的顺时针K2个数加上x。 
  4. (2)"reverse",翻转,从当前指针指针位置开始的顺时针的K2个数。 
  5. (3)"insert x",在当前指针位置的顺时候方向插入一个数x。 
  6. (4)”delete“,删除当前指针所指的数。 
  7. (5)"move x”,如果x=1,指针逆时针旋转,如果x=2,顺时针旋转。 
  8. (6)“query",查询指针所指向的数的值。 
  9. Splay的作法就不说了。 
  10. 还可以有三个双端队列加两个标记搞定,方法,是第一个双端队列que1维护前K1个数, 
  11. 第二个que2维护第K1+1到第K2个数,第三个que3维护接下的数,标记add, 
  12. 表示que1和que2里的数要加上多少,标记head,表示que1是否被翻转过。 
  13. Splay(姿势1): 
  14. */  
  15. #include <iostream>  
  16. #include <cstdio>  
  17. #include <cstring>  
  18. #include <string>  
  19. #include <vector>  
  20. #include <algorithm>  
  21. #include <queue>  
  22. #include <set>  
  23. #include <map>  
  24. using namespace std;  
  25.   
  26. typedef long long LL;  
  27. typedef pair<int,int> PII;  
  28.   
  29. #define LL(x)    (ch[x][0])  
  30. #define RR(x)    (ch[x][1])  
  31. #define Kt       (ch[ ch[Rt][1] ][0])  
  32. #define MID(a,b) (a+((b-a)>>1))  
  33.   
  34. const int N=1e6+5;  
  35.   
  36. int n,m,k1,k2;  
  37. int a[N/2];  
  38.   
  39. struct SplayTree  
  40. {  
  41.     int Rt,top;  
  42.     int pre[N],sz[N],ch[N][2];  
  43.   
  44.     int key[N],add[N],pos;  
  45.     bool flip[N];  
  46.   
  47.     inline void Link(int x,int y,int f)  
  48.     {  
  49.         pre[x]=y; if(y) ch[y][f]=x;  
  50.     }  
  51.     inline void Rotate(int x,int f)  
  52.     {  
  53.         int y=pre[x],z=pre[y];  
  54.   
  55.         PushDown(y); PushDown(x);  
  56.   
  57.         Link(x,z,RR(z)==y);  
  58.         Link(ch[x][f],y,!f);  
  59.         Link(y,x,f);  
  60.   
  61.         PushUp(y);  
  62.     }  
  63.     inline void Splay(int x,int goal)  
  64.     {  
  65.         while(pre[x]!=goal)  
  66.         {  
  67.             int y=pre[x],z=pre[y];  
  68.             int cx=(LL(y)==x),cy=(LL(z)==y);  
  69.             if(z==goal) Rotate(x,cx);  
  70.             else  
  71.             {  
  72.                 if(cx==cy) Rotate(y,cy);  
  73.                 else Rotate(x,cx);  
  74.                 Rotate(x,cy);  
  75.             }  
  76.         }  
  77.         PushUp(x);  
  78.         if(goal==0) Rt=x;  
  79.     }  
  80.     inline void Select(int K,int goal)  
  81.     {  
  82.         int x=Rt;  
  83.         PushDown(x);  
  84.         while(1)  
  85.         {  
  86.             if(sz[LL(x)]>=K) x=LL(x);  
  87.             else if(sz[LL(x)]+1==K) break;  
  88.             else K-=sz[LL(x)]+1,x=RR(x);  
  89.             PushDown(x);  
  90.         }  
  91.         Splay(x,goal);  
  92.     }  
  93.   
  94.     inline void fun_add(int x,int valu)  
  95.     {  
  96.         add[x]+=valu;  
  97.         key[x]+=valu;  
  98.     }  
  99.     inline void fun_flip(int x)  
  100.     {  
  101.         flip[x]^=1;  
  102.         swap(LL(x),RR(x));  
  103.     }  
  104.     inline void PushDown(int x)  
  105.     {  
  106.         if(add[x])  
  107.         {  
  108.             fun_add(LL(x),add[x]);  
  109.             fun_add(RR(x),add[x]);  
  110.             add[x]=0;  
  111.         }  
  112.         if(flip[x])  
  113.         {  
  114.             fun_flip(LL(x));  
  115.             fun_flip(RR(x));  
  116.             flip[x]=0;  
  117.         }  
  118.     }  
  119.     inline void PushUp(int x)  
  120.     {  
  121.         sz[x]=1+sz[LL(x)]+sz[RR(x)];  
  122.     }  
  123.     inline void Add(int x)  
  124.     {  
  125.         Select(1,0); Select(k2+2,Rt);  
  126.         fun_add(Kt,x);  
  127.     }  
  128.     inline void Reverse()  
  129.     {  
  130.         Select(1,0); Select(k1+2,Rt);  
  131.         fun_flip(Kt);  
  132.     }  
  133.     inline void Insert(int x,int pos)  
  134.     {  
  135.         Select(pos,0); Select(pos+1,Rt);  
  136.         addNode(x,Kt,RR(Rt));  
  137.         PushUp(RR(Rt)); PushUp(Rt);  
  138.     }  
  139.     inline int Delete(bool top)  
  140.     {  
  141.         int valu;  
  142.         if(top)  
  143.         {  
  144.             Select(1,0);    Select(3,Rt);  
  145.             valu=key[Kt];  
  146.             Kt=0;  
  147.             PushUp(RR(Rt)); PushUp(Rt);  
  148.         }  
  149.         else  
  150.         {  
  151.             int len=sz[Rt];  
  152.             Select(len-2,0);Select(len,Rt);  
  153.             valu=key[Kt];  
  154.             Kt=0;  
  155.             PushUp(RR(Rt)); PushUp(Rt);  
  156.         }  
  157.         return valu;  
  158.     }  
  159.     inline void Move(int x)  
  160.     {  
  161.         if(x==1)  
  162.         {  
  163.             int valu=Delete(0);  
  164.             Insert(valu,1);  
  165.         }  
  166.         else  
  167.         {  
  168.             int valu=Delete(1);  
  169.             Insert(valu,sz[Rt]-1);  
  170.         }  
  171.     }  
  172.     inline void Query()  
  173.     {  
  174.         Select(2,0);  
  175.         printf("%d\n",key[Rt]);  
  176.     }  
  177.   
  178. //    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }  
  179. //    void Travel(int x)  
  180. //    {  
  181. //        if(x==0) return;  
  182. //  
  183. //        PushDown(x);  
  184. //        Travel(LL(x));  
  185. //        printf("node:%d,pre:%d,sz:%d,LL:%d,RR:%d,key:%d\n",  
  186. //               x,pre[x],sz[x],LL(x),RR(x),key[x]);  
  187. //        Travel(RR(x));  
  188. //    }  
  189.   
  190.     void addNode(int valu,int &x,int f)  
  191.     {  
  192.         x=++top;  
  193.         pre[x]=f; sz[x]=1; LL(x)=RR(x)=0;  
  194.   
  195.         key[x]=valu; add[x]=flip[x]=0;  
  196.     }  
  197.     void build(int lft,int rht,int &x,int f)  
  198.     {  
  199.         if(lft>rht) return;  
  200.   
  201.         int mid=MID(lft,rht);  
  202.         addNode(a[mid],x,f);  
  203.         build(lft,mid-1,LL(x),x);  
  204.         build(mid+1,rht,RR(x),x);  
  205.         PushUp(x);  
  206.     }  
  207.     void init()  
  208.     {  
  209.         Rt=top=0;  
  210.         pre[0]=sz[0]=LL(0)=RR(0)=0;  
  211.   
  212.         addNode(0,Rt,0);    addNode(0,RR(Rt),Rt);  
  213.         build(0,n-1,Kt,RR(Rt));  
  214.         PushUp(RR(Rt));     PushUp(Rt);  
  215.     }  
  216. }spt;  
  217. int main()  
  218. {  
  219.     int t_cnt=0;  
  220.     while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)  
  221.     {  
  222.         if(n==0&&m==0&&k1==0&&k2==0) break;  
  223.   
  224.         for(int i=0;i<n;i++) scanf("%d",&a[i]);  
  225.   
  226.         spt.init();  
  227.   
  228.         printf("Case #%d:\n",++t_cnt);  
  229.   
  230.         char op[100]; int x;  
  231.         while(m--)  
  232.         {  
  233.             scanf("%s",op);  
  234.             if(op[0]=='a')  
  235.             {  
  236.                 scanf("%d",&x); spt.Add(x);  
  237.             }  
  238.             else if(op[0]=='r') spt.Reverse();  
  239.             else if(op[0]=='i')  
  240.             {  
  241.                 scanf("%d",&x); spt.Insert(x,2);  
  242.             }  
  243.             else if(op[0]=='d') spt.Delete(1);  
  244.             else if(op[0]=='m')  
  245.             {  
  246.                 scanf("%d",&x); spt.Move(x);  
  247.             }  
  248.             else spt.Query();  
  249.         }  
  250.     }  
  251.     return 0;  
  252. }  
  253.   
  254.   
  255. Spaly(姿势2):  
  256.   
  257. #include <iostream>  
  258. #include <cstdio>  
  259. #include <cstring>  
  260. using namespace std;  
  261.   
  262. #define LL(x) (ch[x][0])  
  263. #define RR(x) (ch[x][1])  
  264. #define Kt    (ch[ ch[Rt][1] ][0])  
  265. #define MID(a,b)   (a+((b-a)>>1))  
  266.   
  267. const int N=1e6+5;  
  268.   
  269. int a[N/2];  
  270. int n,m,K1,K2,pos;  
  271.   
  272. struct SplayTree  
  273. {  
  274.     int Rt,top;  
  275.     int sz[N],pre[N],ch[N][2];  
  276.   
  277.     bool flip[N];  
  278.     int key[N],add[N];  
  279.   
  280.     inline void Link(int x,int y,int f)  
  281.     {  
  282.         pre[x]=y; if(y) ch[y][f]=x;  
  283.     }  
  284.     inline void Rotate(int x,int f)  
  285.     {  
  286.         int y=pre[x],z=pre[y];  
  287.   
  288.         PushDown(y); PushDown(x);  
  289.         Link(x,z,RR(z)==y);  
  290.         Link(ch[x][f],y,!f);  
  291.         Link(y,x,f);  
  292.         PushUp(y);  
  293.     }  
  294.     inline void Splay(int x,int goal)  
  295.     {  
  296.         while(pre[x]!=goal)  
  297.         {  
  298.             int y=pre[x],z=pre[y];  
  299.             int cx=(LL(y)==x),cy=(LL(z)==y);  
  300.             if(z==goal) Rotate(x,cx);  
  301.             else  
  302.             {  
  303.                 if(cx==cy) Rotate(y,cy);  
  304.                 else Rotate(x,cx);  
  305.                 Rotate(x,cy);  
  306.             }  
  307.         }  
  308.         PushUp(x);  
  309.         if(goal==0) Rt=x;  
  310.     }  
  311.     inline void Select(int K,int goal)  
  312.     {  
  313.         int x=Rt;  
  314.         PushDown(x);  
  315.         while(1)  
  316.         {  
  317.             if(sz[LL(x)]>=K) x=LL(x);  
  318.             else if(1+sz[LL(x)]==K) break;  
  319.             else K-=sz[LL(x)]+1,x=RR(x);  
  320.             PushDown(x);  
  321.         }  
  322.         Splay(x,goal);  
  323.     }  
  324.   
  325.     inline void fun_add(int x,int valu)  
  326.     {  
  327.         key[x]+=valu;  
  328.         add[x]+=valu;  
  329.     }  
  330.     inline void fun_flip(int x)  
  331.     {  
  332.         flip[x]^=1;  
  333.         swap(LL(x),RR(x));  
  334.     }  
  335.     inline void PushUp(int x)  
  336.     {  
  337.         sz[x]=1+sz[LL(x)]+sz[RR(x)];  
  338.     }  
  339.     inline void PushDown(int x)  
  340.     {  
  341.         if(add[x])  
  342.         {  
  343.             fun_add(LL(x),add[x]);  
  344.             fun_add(RR(x),add[x]);  
  345.             add[x]=0;  
  346.         }  
  347.         if(flip[x])  
  348.         {  
  349.             fun_flip(LL(x)); fun_flip(RR(x));  
  350.             flip[x]=0;  
  351.         }  
  352.     }  
  353.     inline void Add(int st,int ed,int valu)  
  354.     {  
  355.         Select(st-1,0); Select(ed+1,Rt);  
  356.         fun_add(Kt,valu);  
  357.     }  
  358.     inline void Reverse(int st,int ed)  
  359.     {  
  360.         Select(st-1,0); Select(ed+1,Rt);  
  361.         fun_flip(Kt);  
  362.     }  
  363.     inline void Insert(int pos,int valu)  
  364.     {  
  365.         Select(pos,0);  Select(pos+1,Rt);  
  366.         addNode(valu,Kt,RR(Rt));  
  367.         PushUp(RR(Rt)); PushUp(Rt);  
  368.     }  
  369.     inline void Delete(int pos)  
  370.     {  
  371.         Select(pos-1,0); Select(pos+1,Rt);  
  372.         Kt=0;  PushUp(RR(Rt)); PushUp(Rt);  
  373.     }  
  374.     inline void Query(int pos)  
  375.     {  
  376.         Select(pos,0);  
  377.         printf("%d\n",key[Rt]);  
  378.     }  
  379.     inline void Move(int len)  
  380.     {  
  381.         pos-=len;  
  382.         Select(1,0);    Select(2+len,Rt);  
  383.         int r1=Kt;      Kt=0;  
  384.         PushUp(RR(Rt)); PushUp(Rt);  
  385.   
  386.         Select(sz[Rt]-1,0); Select(sz[Rt],Rt);  
  387.         Link(r1,RR(Rt),0);  
  388.         PushUp(RR(Rt)); PushUp(Rt);  
  389.     }  
  390.   
  391.     inline void addNode(int valu,int &x,int f)  
  392.     {  
  393.         x=++top;  
  394.   
  395.         sz[x]=1; pre[x]=f; LL(x)=RR(x)=0;  
  396.   
  397.         key[x]=valu; add[x]=flip[x]=0;  
  398.     }  
  399.     void build(int lft,int rht,int &x,int f)  
  400.     {  
  401.         if(lft>rht) return;  
  402.   
  403.         int mid=MID(lft,rht);  
  404.         addNode(a[mid],x,f);  
  405.         build(lft,mid-1,LL(x),x);  
  406.         build(mid+1,rht,RR(x),x);  
  407.         PushUp(x);  
  408.     }  
  409.     void init()  
  410.     {  
  411.         Rt=top=0;  
  412.   
  413.         addNode(0,Rt,0); addNode(0,RR(Rt),Rt);  
  414.   
  415.         build(0,n-1,Kt,RR(Rt));  
  416.         PushUp(RR(Rt));  PushUp(Rt);  
  417.     }  
  418.   
  419. //    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }  
  420. //    void Travel(int x)  
  421. //    {  
  422. //        if(x==0) return;  
  423. //        PushDown(x);  
  424. //        Travel(LL(x));  
  425. //        printf("node:%d,sz:%d,pre:%d,LL:%d,RR:%d,key:%d\n",  
  426. //               x,sz[x],pre[x],LL(x),RR(x),key[x]);  
  427. //        Travel(RR(x));  
  428. //    }  
  429. }spt;  
  430. void deal(int &pos,int len)  
  431. {  
  432.     if(pos<=1) pos=len-1;  
  433.     if(pos>=len) pos=2;  
  434. }  
  435. int main()  
  436. {  
  437.     freopen("in.txt","r",stdin);  
  438.   
  439.     int t_cnt=0;  
  440.     while(scanf("%d%d%d%d",&n,&m,&K1,&K2)!=EOF)  
  441.     {  
  442.         if(n==0&&m==0&&K1==0&&K2==0) break;  
  443.   
  444.         for(int i=0;i<n;i++) scanf("%d",&a[i]);  
  445.   
  446.         spt.init(); pos=2;  
  447.   
  448.         printf("Case #%d:\n",++t_cnt);  
  449.   
  450.         char op[100]; int x;  
  451.         while(m--)  
  452.         {  
  453.             int len=spt.sz[spt.Rt];  
  454.             scanf("%s",op);  
  455.             if(op[0]=='a')  
  456.             {  
  457.                 scanf("%d",&x);  
  458.                 if(pos+K2>len) spt.Move(pos+K2-len);  
  459.                 spt.Add(pos,pos+K2-1,x);  
  460.             }  
  461.             else if(op[0]=='r')  
  462.             {  
  463.                 if(pos+K1>=len) spt.Move(pos+K1-len);  
  464.                 spt.Reverse(pos,pos+K1-1);  
  465.             }  
  466.             else if(op[0]=='i')  
  467.             {  
  468.                 scanf("%d",&x); spt.Insert(pos,x);  
  469.             }  
  470.             else if(op[0]=='d')  
  471.             {  
  472.                 spt.Delete(pos);  
  473.                 deal(pos,spt.sz[spt.Rt]);  
  474.             }  
  475.             else if(op[0]=='m')  
  476.             {  
  477.                 scanf("%d",&x);  
  478.                 if(x==1) pos--;  
  479.                 else pos++;  
  480.                 deal(pos,len);  
  481.             }  
  482.             else if(op[0]=='q') spt.Query(pos);  
  483. //            spt.Debug();  
  484.         }  
  485.     }  
  486.     return 0;  
  487. }  
  488.   
  489.   
  490. /* 
  491. Description 
  492.  
  493. You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. 
  494.  
  495. Input 
  496.  
  497. The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. 
  498. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. 
  499. Each of the next Q lines represents an operation. 
  500. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000. 
  501. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab. 
  502.  
  503. Output 
  504.  
  505. You need to answer all Q commands in order. One answer in a line. 
  506.  
  507. Sample Input 
  508.  
  509. 10 5 
  510. 1 2 3 4 5 6 7 8 9 10 
  511. Q 4 4 
  512. Q 1 10 
  513. Q 2 4 
  514. C 3 6 3 
  515. Q 2 4 
  516. Sample Output 
  517.  
  518. 4 
  519. 55 
  520. 9 
  521. 15 
  522. http://acm.pku.edu.cn/JudgeOnline/problem?id=3468 
  523. 区间跟新,区间求和 
  524. */  
  525. #include <cstdio>  
  526. #define keyTree (ch[ ch[root][1] ][0])  
  527. const int maxn = 222222;  
  528. struct SplayTree{  
  529.     int sz[maxn];  
  530.     int ch[maxn][2];  
  531.     int pre[maxn];  
  532.     int root , top1 , top2;  
  533.     int ss[maxn] , que[maxn];  
  534.    
  535.     inline void Rotate(int x,int f) {  
  536.         int y = pre[x];  
  537.         push_down(y);  
  538.         push_down(x);  
  539.         ch[y][!f] = ch[x][f];  
  540.         pre[ ch[x][f] ] = y;  
  541.         pre[x] = pre[y];  
  542.         if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;  
  543.         ch[x][f] = y;  
  544.         pre[y] = x;  
  545.         push_up(y);  
  546.     }  
  547.     inline void Splay(int x,int goal) {  
  548.         push_down(x);  
  549.         while(pre[x] != goal) {  
  550.             if(pre[pre[x]] == goal) {  
  551.                 Rotate(x , ch[pre[x]][0] == x);  
  552.             } else {  
  553.                 int y = pre[x] , z = pre[y];  
  554.                 int f = (ch[z][0] == y);  
  555.                 if(ch[y][f] == x) {  
  556.                     Rotate(x , !f) , Rotate(x , f);  
  557.                 } else {  
  558.                     Rotate(y , f) , Rotate(x , f);  
  559.                 }  
  560.             }  
  561.         }  
  562.         push_up(x);  
  563.         if(goal == 0) root = x;  
  564.     }  
  565.     inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边  
  566.         int x = root;  
  567.         push_down(x);  
  568.         while(sz[ ch[x][0] ] != k) {  
  569.             if(k < sz[ ch[x][0] ]) {  
  570.                 x = ch[x][0];  
  571.             } else {  
  572.                 k -= (sz[ ch[x][0] ] + 1);  
  573.                 x = ch[x][1];  
  574.             }  
  575.             push_down(x);  
  576.         }  
  577.         Splay(x,goal);  
  578.     }  
  579.     inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存  
  580.         int father = pre[x];  
  581.         int head = 0 , tail = 0;  
  582.         for (que[tail++] = x ; head < tail ; head ++) {  
  583.             ss[top2 ++] = que[head];  
  584.             if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];  
  585.             if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];  
  586.         }  
  587.         ch[ father ][ ch[father][1] == x ] = 0;  
  588.         pushup(father);  
  589.     }  
  590.     //以上一般不修改//  
  591.     void debug() {printf("%d\n",root);Treaval(root);}  
  592.     void Treaval(int x) {  
  593.         if(x) {  
  594.             Treaval(ch[x][0]);  
  595.             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);  
  596.             Treaval(ch[x][1]);  
  597.         }  
  598.     }  
  599.     //以上Debug  
  600.    
  601.    
  602.     //以下是题目的特定函数:  
  603.     inline void NewNode(int &x,int c) {  
  604.         if (top2) x = ss[--top2];//用栈手动压的内存池  
  605.         else x = ++top1;  
  606.         ch[x][0] = ch[x][1] = pre[x] = 0;  
  607.         sz[x] = 1;  
  608.    
  609.         val[x] = sum[x] = c;/*这是题目特定函数*/  
  610.         add[x] = 0;  
  611.     }  
  612.    
  613.     //把延迟标记推到孩子  
  614.     inline void push_down(int x) {/*这是题目特定函数*/  
  615.         if(add[x]) {  
  616.             val[x] += add[x];  
  617.             add[ ch[x][0] ] += add[x];  
  618.             add[ ch[x][1] ] += add[x];   
  619.             sum[ ch[x][0] ] += (long long)sz[ ch[x][0] ] * add[x];  
  620.             sum[ ch[x][1] ] += (long long)sz[ ch[x][1] ] * add[x];  
  621.             add[x] = 0;  
  622.         }  
  623.     }  
  624.     //把孩子状态更新上来  
  625.     inline void push_up(int x) {      
  626.         sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];  
  627.         /*这是题目特定函数*/  
  628.         sum[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];  
  629.     }  
  630.    
  631.     /*初始化*/  
  632.     inline void makeTree(int &x,int l,int r,int f) {  
  633.         if(l > r) return ;  
  634.         int m = (l + r)>>1;  
  635.         NewNode(x , num[m]);        /*num[m]权值改成题目所需的*/  
  636.         makeTree(ch[x][0] , l , m - 1 , x);  
  637.         makeTree(ch[x][1] , m + 1 , r , x);  
  638.         pre[x] = f;  
  639.         push_up(x);  
  640.     }  
  641.     inline void init(int n) {/*这是题目特定函数*/  
  642.         ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;  
  643.         add[0] = sum[0] = 0;  
  644.    
  645.         root = top1 = 0;  
  646.         //为了方便处理边界,加两个边界顶点  
  647.         NewNode(root , -1);  
  648.         NewNode(ch[root][1] , -1);  
  649.         pre[top1] = root;  
  650.         sz[root] = 2;  
  651.    
  652.    
  653.         for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]);  
  654.         makeTree(keyTree , 0 , n-1 , ch[root][1]);  
  655.         push_up(ch[root][1]);  
  656.         push_up(root);  
  657.     }  
  658.     /*更新*/  
  659.     inline void update( ) {/*这是题目特定函数*/  
  660.         int l , r , c;  
  661.         scanf("%d%d%d",&l,&r,&c);  
  662.         RotateTo(l-1,0);  
  663.         RotateTo(r+1,root);       
  664.         add[ keyTree ] += c;  
  665.         sum[ keyTree ] += (long long)c * sz[ keyTree ];  
  666.     }  
  667.     /*询问*/  
  668.     inline void query() {/*这是题目特定函数*/  
  669.         int l , r;  
  670.         scanf("%d%d",&l,&r);  
  671.         RotateTo(l-1 , 0);  
  672.         RotateTo(r+1 , root);  
  673.         printf("%lld\n",sum[keyTree]);  
  674.     }  
  675.    
  676.    
  677.     /*这是题目特定变量*/  
  678.     int num[maxn];  
  679.     int val[maxn];  
  680.     int add[maxn];  
  681.     long long sum[maxn];  
  682. }spt;  
  683.    
  684.    
  685. int main() {  
  686.     int n , m;  
  687.     scanf("%d%d",&n,&m);  
  688.     spt.init(n);  
  689.     while(m --) {  
  690.         char op[2];  
  691.         scanf("%s",op);  
  692.         if(op[0] == 'Q') {  
  693.             spt.query();  
  694.         } else {  
  695.             spt.update();  
  696.         }  
  697.     }  
  698.     return 0;  
  699. }  





7:动态树


8:斯坦纳树


9:主席树


10:QTree


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值