1:Trie 字典树
字典树
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。
它有3个基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 每个节点的所有子节点包含的字符都不相同。
详细应用见 http://blog.csdn.net/metalseed/article/details/7953262- #include <iostream>
- using namespace std;
- #define MAX 26 //字符集大小
- typedef struct TrieNode {
- int nCount;
- struct TrieNode *next[MAX];
- }TrieNode;
- TrieNode Memory[1000000];
- int allocp =0;
- TrieNode *CreateTrieNode() {
- int i;
- TrieNode *p;
- p = &Memory[allocp++];
- p->nCount = 1;
- for(i =0 ; i < MAX ; i++) {
- p->next[i] = NULL;
- }
- return p;
- }
- void InsertTrie(TrieNode * &pRoot , char*s) {
- int i, k;
- TrieNode *p;
- if(!(p = pRoot)) {
- p = pRoot = CreateTrieNode();
- }
- i = 0;
- while(s[i]) {
- k = s[i++] - 'a';
- if(p->next[k])
- p->next[k]->nCount++;
- else
- p->next[k] = CreateTrieNode();
- p = p->next[k];
- }
- }
- /*查询该前缀出现次数*/
- /*若查询该词出现次数
- 则所有的count初始化为0
- 并去除所有对count的操作
- 只在每次InsertTrie末尾加 p->nCount++;
- */
- int SearchTrie(TrieNode * &pRoot , char*s) {
- TrieNode *p;
- int i , k;
- if(!(p = pRoot)) {
- return 0;
- }
- i = 0;
- while(s[i]) {
- k = s[i++] -'a';
- if(p->next[k] == NULL) return 0;
- p = p->next[k];
- }
- return p->nCount;
- }
- int main()
- {
- TrieNode *ROOT = NULL;
- InsertTrie(ROOT,"see");
- InsertTrie(ROOT,"seeda");
- InsertTrie(ROOT,"seedb");
- InsertTrie(ROOT,"seeda");
- cout<<SearchTrie(ROOT,"seeda")<<endl;
- cout<<SearchTrie(ROOT,"seedb")<<endl;
- cout<<SearchTrie(ROOT,"see")<<endl;
- return 0;
- }
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模板)- #include<iostream>
- #include<algorithm>
- using namespace std;
- /* 1D */
- const int maxn = 10000;
- int tree[maxn],maxID = 0xff/*数组长度,由题定,建树用update*/;
- inline void init()
- {
- memset(tree,0,sizeof(tree));
- }
- inline int read(int idx){ /*求前idx项和*/
- int sum = 0;
- while (idx > 0){
- sum += tree[idx];
- idx -= (idx & -idx);
- }
- return sum;
- }
- inline int readSingle(int idx){ /*求idx单点值*/
- int sum = tree[idx];
- if (idx > 0){
- int z = idx - (idx & -idx);
- idx--;
- while (idx != z){
- sum -= tree[idx];
- idx -= (idx & -idx);
- }
- }
- return sum;
- }
- inline void update(int idx ,int val){ /*给idx位置叠加val,叠加!*/
- while (idx <= maxID){
- tree[idx] += val;
- idx += (idx & -idx);
- }
- }
- int main()
- {
- cout << read(10) << endl;
- for(int i = 0; i< 10; ++i)
- {
- update(i+1,i+1);
- }
- update(4,999);
- cout << read(1) << endl;
- cout << read(3) << endl;
- cout << readSingle(4) << endl;
- return 0;
- }
4:Segment Tree 线段树
成段加C 区间求和
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- #define lson l , m , rt << 1
- #define rson m + 1 , r , rt << 1 | 1
- #define LL long long
- const int maxn = 111111;
- /* Node Begin */
- LL add[maxn<<2];
- LL sum[maxn<<2];
- /* Node End */
- void PushUp(int rt) {
- sum[rt] = sum[rt<<1] + sum[rt<<1|1];
- }
- void PushDown(int rt,int m) {
- if (add[rt]) {
- add[rt<<1] += add[rt];
- add[rt<<1|1] += add[rt];
- sum[rt<<1] += add[rt] * (m - (m >> 1));
- sum[rt<<1|1] += add[rt] * (m >> 1);
- add[rt] = 0;
- }
- }
- void build(int l,int r,int rt) {
- add[rt] = 0;
- if (l == r) {
- scanf("%lld",&sum[rt]);
- return ;
- }
- int m = (l + r) >> 1;
- build(lson);
- build(rson);
- PushUp(rt);
- }
- void update(int L,int R,int c,int l,int r,int rt) {
- if (L <= l && r <= R) {
- add[rt] += c;
- sum[rt] += (LL)c * (r - l + 1);
- return ;
- }
- PushDown(rt , r - l + 1);
- int m = (l + r) >> 1;
- if (L <= m) update(L , R , c , lson);
- if (m < R) update(L , R , c , rson);
- PushUp(rt);
- }
- LL query(int L,int R,int l,int r,int rt) {
- if (L <= l && r <= R) {
- return sum[rt];
- }
- PushDown(rt , r - l + 1);
- int m = (l + r) >> 1;
- LL ret = 0;
- if (L <= m) ret += query(L , R , lson);
- if (m < R) ret += query(L , R , rson);
- return ret;
- }
- int main() {
- int N , Q;
- scanf("%d%d",&N,&Q);
- build(1 , N , 1);
- while (Q --) {
- char op[2];
- int a , b , c;
- scanf("%s",op);
- if (op[0] == 'Q')
- {
- scanf("%d%d",&a,&b);
- printf("%lld\n",query(a , b , 1 , N , 1));
- }
- else
- {
- scanf("%d%d%d",&a,&b,&c);
- update(a , b , c , 1 , N , 1);
- }
- }
- return 0;
- }
5:SBT 二叉平衡检索树
http://acm.hdu.edu.cn/showproblem.php?pid=4006
- #include <stdio.h>
- #include <string.h>
- #define MAX 1000010
- int n,m;
- struct SBT {
- int left,right,size,key;
- void Init() {
- left = right = 0;
- size = 1;
- }
- }a[MAX];
- int tot,root;
- void left_rotate(int &t) {
- int k = a[t].right;
- a[t].right = a[k].left;
- a[k].left = t;
- a[k].size = a[t].size;
- a[t].size = a[a[t].left].size + a[a[t].right].size + 1;
- t = k;
- }
- void right_rotate(int &t) {
- int k = a[t].left;
- a[t].left = a[k].right;
- a[k].right = t;
- a[k].size = a[t].size;
- a[t].size = a[a[t].left].size + a[a[t].right].size + 1;
- t = k;
- }
- void maintain(int &t,int flag) {
- if (flag == 0) {
- if (a[a[a[t].left].left].size > a[a[t].right].size)
- right_rotate(t);
- else if (a[a[a[t].left].right].size > a[a[t].right].size)
- left_rotate(a[t].left),right_rotate(t);
- else return;
- }
- else {
- if (a[a[a[t].right].right].size > a[a[t].left].size)
- left_rotate(t);
- else if (a[a[a[t].right].left].size > a[a[t].left].size)
- right_rotate(a[t].right),left_rotate(t);
- else return;
- }
- maintain(a[t].left,0);
- maintain(a[t].right,1);
- maintain(t,0);
- maintain(t,1);
- }
- void insert(int &t,int v) {
- if (t == 0)
- t = ++tot,a[t].Init(),a[t].key = v;
- else {
- a[t].size++;
- if (v < a[t].key)
- insert(a[t].left,v);
- else insert(a[t].right,v);
- maintain(t,v>=a[t].key);
- }
- }
- int del(int &t,int v) {
- if (!t) return 0;
- a[t].size--;
- if (v == a[t].key || v < a[t].key && !a[t].left
- || v > a[t].key && !a[t].right) {
- if (a[t].left && a[t].right) {
- int p = del(a[t].left,v+1);
- a[t].key = a[p].key;
- return p;
- }
- else {
- int p = t;
- t = a[t].left + a[t].right;
- return p;
- }
- }
- else return del(v<a[t].key?a[t].left:a[t].right,v);
- }
- int find(int t,int k) {
- if (k <= a[a[t].left].size)
- return find(a[t].left,k);
- if (k > a[a[t].left].size + 1)
- return find(a[t].right,k-a[a[t].left].size-1);
- return a[t].key;
- }
- int main()
- {
- int i,j,k;
- while (scanf("%d%d",&n,&m) != EOF) {
- tot = root = 0;
- char ope[10];
- while (n--) {
- scanf("%s",ope);
- if (ope[0] == 'I') {
- scanf("%d",&k);
- insert(root,k);
- }
- else printf("%d\n",find(root,a[root].size+1-m));
- }
- }
- }
6:Splay 伸展树
- /*
- 题意:有N个数字围成一个圈,有M个操作,操作类型有六种:
- (1)“add x",从当前指针位置开始的顺时针K2个数加上x。
- (2)"reverse",翻转,从当前指针指针位置开始的顺时针的K2个数。
- (3)"insert x",在当前指针位置的顺时候方向插入一个数x。
- (4)”delete“,删除当前指针所指的数。
- (5)"move x”,如果x=1,指针逆时针旋转,如果x=2,顺时针旋转。
- (6)“query",查询指针所指向的数的值。
- Splay的作法就不说了。
- 还可以有三个双端队列加两个标记搞定,方法,是第一个双端队列que1维护前K1个数,
- 第二个que2维护第K1+1到第K2个数,第三个que3维护接下的数,标记add,
- 表示que1和que2里的数要加上多少,标记head,表示que1是否被翻转过。
- Splay(姿势1):
- */
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <algorithm>
- #include <queue>
- #include <set>
- #include <map>
- using namespace std;
- typedef long long LL;
- typedef pair<int,int> PII;
- #define LL(x) (ch[x][0])
- #define RR(x) (ch[x][1])
- #define Kt (ch[ ch[Rt][1] ][0])
- #define MID(a,b) (a+((b-a)>>1))
- const int N=1e6+5;
- int n,m,k1,k2;
- int a[N/2];
- struct SplayTree
- {
- int Rt,top;
- int pre[N],sz[N],ch[N][2];
- int key[N],add[N],pos;
- bool flip[N];
- inline void Link(int x,int y,int f)
- {
- pre[x]=y; if(y) ch[y][f]=x;
- }
- inline void Rotate(int x,int f)
- {
- int y=pre[x],z=pre[y];
- PushDown(y); PushDown(x);
- Link(x,z,RR(z)==y);
- Link(ch[x][f],y,!f);
- Link(y,x,f);
- PushUp(y);
- }
- inline void Splay(int x,int goal)
- {
- while(pre[x]!=goal)
- {
- int y=pre[x],z=pre[y];
- int cx=(LL(y)==x),cy=(LL(z)==y);
- if(z==goal) Rotate(x,cx);
- else
- {
- if(cx==cy) Rotate(y,cy);
- else Rotate(x,cx);
- Rotate(x,cy);
- }
- }
- PushUp(x);
- if(goal==0) Rt=x;
- }
- inline void Select(int K,int goal)
- {
- int x=Rt;
- PushDown(x);
- while(1)
- {
- if(sz[LL(x)]>=K) x=LL(x);
- else if(sz[LL(x)]+1==K) break;
- else K-=sz[LL(x)]+1,x=RR(x);
- PushDown(x);
- }
- Splay(x,goal);
- }
- inline void fun_add(int x,int valu)
- {
- add[x]+=valu;
- key[x]+=valu;
- }
- inline void fun_flip(int x)
- {
- flip[x]^=1;
- swap(LL(x),RR(x));
- }
- inline void PushDown(int x)
- {
- if(add[x])
- {
- fun_add(LL(x),add[x]);
- fun_add(RR(x),add[x]);
- add[x]=0;
- }
- if(flip[x])
- {
- fun_flip(LL(x));
- fun_flip(RR(x));
- flip[x]=0;
- }
- }
- inline void PushUp(int x)
- {
- sz[x]=1+sz[LL(x)]+sz[RR(x)];
- }
- inline void Add(int x)
- {
- Select(1,0); Select(k2+2,Rt);
- fun_add(Kt,x);
- }
- inline void Reverse()
- {
- Select(1,0); Select(k1+2,Rt);
- fun_flip(Kt);
- }
- inline void Insert(int x,int pos)
- {
- Select(pos,0); Select(pos+1,Rt);
- addNode(x,Kt,RR(Rt));
- PushUp(RR(Rt)); PushUp(Rt);
- }
- inline int Delete(bool top)
- {
- int valu;
- if(top)
- {
- Select(1,0); Select(3,Rt);
- valu=key[Kt];
- Kt=0;
- PushUp(RR(Rt)); PushUp(Rt);
- }
- else
- {
- int len=sz[Rt];
- Select(len-2,0);Select(len,Rt);
- valu=key[Kt];
- Kt=0;
- PushUp(RR(Rt)); PushUp(Rt);
- }
- return valu;
- }
- inline void Move(int x)
- {
- if(x==1)
- {
- int valu=Delete(0);
- Insert(valu,1);
- }
- else
- {
- int valu=Delete(1);
- Insert(valu,sz[Rt]-1);
- }
- }
- inline void Query()
- {
- Select(2,0);
- printf("%d\n",key[Rt]);
- }
- // void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
- // void Travel(int x)
- // {
- // if(x==0) return;
- //
- // PushDown(x);
- // Travel(LL(x));
- // printf("node:%d,pre:%d,sz:%d,LL:%d,RR:%d,key:%d\n",
- // x,pre[x],sz[x],LL(x),RR(x),key[x]);
- // Travel(RR(x));
- // }
- void addNode(int valu,int &x,int f)
- {
- x=++top;
- pre[x]=f; sz[x]=1; LL(x)=RR(x)=0;
- key[x]=valu; add[x]=flip[x]=0;
- }
- void build(int lft,int rht,int &x,int f)
- {
- if(lft>rht) return;
- int mid=MID(lft,rht);
- addNode(a[mid],x,f);
- build(lft,mid-1,LL(x),x);
- build(mid+1,rht,RR(x),x);
- PushUp(x);
- }
- void init()
- {
- Rt=top=0;
- pre[0]=sz[0]=LL(0)=RR(0)=0;
- addNode(0,Rt,0); addNode(0,RR(Rt),Rt);
- build(0,n-1,Kt,RR(Rt));
- PushUp(RR(Rt)); PushUp(Rt);
- }
- }spt;
- int main()
- {
- int t_cnt=0;
- while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
- {
- if(n==0&&m==0&&k1==0&&k2==0) break;
- for(int i=0;i<n;i++) scanf("%d",&a[i]);
- spt.init();
- printf("Case #%d:\n",++t_cnt);
- char op[100]; int x;
- while(m--)
- {
- scanf("%s",op);
- if(op[0]=='a')
- {
- scanf("%d",&x); spt.Add(x);
- }
- else if(op[0]=='r') spt.Reverse();
- else if(op[0]=='i')
- {
- scanf("%d",&x); spt.Insert(x,2);
- }
- else if(op[0]=='d') spt.Delete(1);
- else if(op[0]=='m')
- {
- scanf("%d",&x); spt.Move(x);
- }
- else spt.Query();
- }
- }
- return 0;
- }
- Spaly(姿势2):
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- using namespace std;
- #define LL(x) (ch[x][0])
- #define RR(x) (ch[x][1])
- #define Kt (ch[ ch[Rt][1] ][0])
- #define MID(a,b) (a+((b-a)>>1))
- const int N=1e6+5;
- int a[N/2];
- int n,m,K1,K2,pos;
- struct SplayTree
- {
- int Rt,top;
- int sz[N],pre[N],ch[N][2];
- bool flip[N];
- int key[N],add[N];
- inline void Link(int x,int y,int f)
- {
- pre[x]=y; if(y) ch[y][f]=x;
- }
- inline void Rotate(int x,int f)
- {
- int y=pre[x],z=pre[y];
- PushDown(y); PushDown(x);
- Link(x,z,RR(z)==y);
- Link(ch[x][f],y,!f);
- Link(y,x,f);
- PushUp(y);
- }
- inline void Splay(int x,int goal)
- {
- while(pre[x]!=goal)
- {
- int y=pre[x],z=pre[y];
- int cx=(LL(y)==x),cy=(LL(z)==y);
- if(z==goal) Rotate(x,cx);
- else
- {
- if(cx==cy) Rotate(y,cy);
- else Rotate(x,cx);
- Rotate(x,cy);
- }
- }
- PushUp(x);
- if(goal==0) Rt=x;
- }
- inline void Select(int K,int goal)
- {
- int x=Rt;
- PushDown(x);
- while(1)
- {
- if(sz[LL(x)]>=K) x=LL(x);
- else if(1+sz[LL(x)]==K) break;
- else K-=sz[LL(x)]+1,x=RR(x);
- PushDown(x);
- }
- Splay(x,goal);
- }
- inline void fun_add(int x,int valu)
- {
- key[x]+=valu;
- add[x]+=valu;
- }
- inline void fun_flip(int x)
- {
- flip[x]^=1;
- swap(LL(x),RR(x));
- }
- inline void PushUp(int x)
- {
- sz[x]=1+sz[LL(x)]+sz[RR(x)];
- }
- inline void PushDown(int x)
- {
- if(add[x])
- {
- fun_add(LL(x),add[x]);
- fun_add(RR(x),add[x]);
- add[x]=0;
- }
- if(flip[x])
- {
- fun_flip(LL(x)); fun_flip(RR(x));
- flip[x]=0;
- }
- }
- inline void Add(int st,int ed,int valu)
- {
- Select(st-1,0); Select(ed+1,Rt);
- fun_add(Kt,valu);
- }
- inline void Reverse(int st,int ed)
- {
- Select(st-1,0); Select(ed+1,Rt);
- fun_flip(Kt);
- }
- inline void Insert(int pos,int valu)
- {
- Select(pos,0); Select(pos+1,Rt);
- addNode(valu,Kt,RR(Rt));
- PushUp(RR(Rt)); PushUp(Rt);
- }
- inline void Delete(int pos)
- {
- Select(pos-1,0); Select(pos+1,Rt);
- Kt=0; PushUp(RR(Rt)); PushUp(Rt);
- }
- inline void Query(int pos)
- {
- Select(pos,0);
- printf("%d\n",key[Rt]);
- }
- inline void Move(int len)
- {
- pos-=len;
- Select(1,0); Select(2+len,Rt);
- int r1=Kt; Kt=0;
- PushUp(RR(Rt)); PushUp(Rt);
- Select(sz[Rt]-1,0); Select(sz[Rt],Rt);
- Link(r1,RR(Rt),0);
- PushUp(RR(Rt)); PushUp(Rt);
- }
- inline void addNode(int valu,int &x,int f)
- {
- x=++top;
- sz[x]=1; pre[x]=f; LL(x)=RR(x)=0;
- key[x]=valu; add[x]=flip[x]=0;
- }
- void build(int lft,int rht,int &x,int f)
- {
- if(lft>rht) return;
- int mid=MID(lft,rht);
- addNode(a[mid],x,f);
- build(lft,mid-1,LL(x),x);
- build(mid+1,rht,RR(x),x);
- PushUp(x);
- }
- void init()
- {
- Rt=top=0;
- addNode(0,Rt,0); addNode(0,RR(Rt),Rt);
- build(0,n-1,Kt,RR(Rt));
- PushUp(RR(Rt)); PushUp(Rt);
- }
- // void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
- // void Travel(int x)
- // {
- // if(x==0) return;
- // PushDown(x);
- // Travel(LL(x));
- // printf("node:%d,sz:%d,pre:%d,LL:%d,RR:%d,key:%d\n",
- // x,sz[x],pre[x],LL(x),RR(x),key[x]);
- // Travel(RR(x));
- // }
- }spt;
- void deal(int &pos,int len)
- {
- if(pos<=1) pos=len-1;
- if(pos>=len) pos=2;
- }
- int main()
- {
- freopen("in.txt","r",stdin);
- int t_cnt=0;
- while(scanf("%d%d%d%d",&n,&m,&K1,&K2)!=EOF)
- {
- if(n==0&&m==0&&K1==0&&K2==0) break;
- for(int i=0;i<n;i++) scanf("%d",&a[i]);
- spt.init(); pos=2;
- printf("Case #%d:\n",++t_cnt);
- char op[100]; int x;
- while(m--)
- {
- int len=spt.sz[spt.Rt];
- scanf("%s",op);
- if(op[0]=='a')
- {
- scanf("%d",&x);
- if(pos+K2>len) spt.Move(pos+K2-len);
- spt.Add(pos,pos+K2-1,x);
- }
- else if(op[0]=='r')
- {
- if(pos+K1>=len) spt.Move(pos+K1-len);
- spt.Reverse(pos,pos+K1-1);
- }
- else if(op[0]=='i')
- {
- scanf("%d",&x); spt.Insert(pos,x);
- }
- else if(op[0]=='d')
- {
- spt.Delete(pos);
- deal(pos,spt.sz[spt.Rt]);
- }
- else if(op[0]=='m')
- {
- scanf("%d",&x);
- if(x==1) pos--;
- else pos++;
- deal(pos,len);
- }
- else if(op[0]=='q') spt.Query(pos);
- // spt.Debug();
- }
- }
- return 0;
- }
- /*
- Description
- 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.
- Input
- The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
- The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
- Each of the next Q lines represents an operation.
- "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
- "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
- Output
- You need to answer all Q commands in order. One answer in a line.
- Sample Input
- 10 5
- 1 2 3 4 5 6 7 8 9 10
- Q 4 4
- Q 1 10
- Q 2 4
- C 3 6 3
- Q 2 4
- Sample Output
- 4
- 55
- 9
- 15
- http://acm.pku.edu.cn/JudgeOnline/problem?id=3468
- 区间跟新,区间求和
- */
- #include <cstdio>
- #define keyTree (ch[ ch[root][1] ][0])
- const int maxn = 222222;
- struct SplayTree{
- int sz[maxn];
- int ch[maxn][2];
- int pre[maxn];
- int root , top1 , top2;
- int ss[maxn] , que[maxn];
- inline void Rotate(int x,int f) {
- int y = pre[x];
- push_down(y);
- push_down(x);
- ch[y][!f] = ch[x][f];
- pre[ ch[x][f] ] = y;
- pre[x] = pre[y];
- if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
- ch[x][f] = y;
- pre[y] = x;
- push_up(y);
- }
- inline void Splay(int x,int goal) {
- push_down(x);
- while(pre[x] != goal) {
- if(pre[pre[x]] == goal) {
- Rotate(x , ch[pre[x]][0] == x);
- } else {
- int y = pre[x] , z = pre[y];
- int f = (ch[z][0] == y);
- if(ch[y][f] == x) {
- Rotate(x , !f) , Rotate(x , f);
- } else {
- Rotate(y , f) , Rotate(x , f);
- }
- }
- }
- push_up(x);
- if(goal == 0) root = x;
- }
- inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边
- int x = root;
- push_down(x);
- while(sz[ ch[x][0] ] != k) {
- if(k < sz[ ch[x][0] ]) {
- x = ch[x][0];
- } else {
- k -= (sz[ ch[x][0] ] + 1);
- x = ch[x][1];
- }
- push_down(x);
- }
- Splay(x,goal);
- }
- inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存
- int father = pre[x];
- int head = 0 , tail = 0;
- for (que[tail++] = x ; head < tail ; head ++) {
- ss[top2 ++] = que[head];
- if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];
- if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];
- }
- ch[ father ][ ch[father][1] == x ] = 0;
- pushup(father);
- }
- //以上一般不修改//
- void debug() {printf("%d\n",root);Treaval(root);}
- void Treaval(int x) {
- if(x) {
- Treaval(ch[x][0]);
- printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
- Treaval(ch[x][1]);
- }
- }
- //以上Debug
- //以下是题目的特定函数:
- inline void NewNode(int &x,int c) {
- if (top2) x = ss[--top2];//用栈手动压的内存池
- else x = ++top1;
- ch[x][0] = ch[x][1] = pre[x] = 0;
- sz[x] = 1;
- val[x] = sum[x] = c;/*这是题目特定函数*/
- add[x] = 0;
- }
- //把延迟标记推到孩子
- inline void push_down(int x) {/*这是题目特定函数*/
- if(add[x]) {
- val[x] += add[x];
- add[ ch[x][0] ] += add[x];
- add[ ch[x][1] ] += add[x];
- sum[ ch[x][0] ] += (long long)sz[ ch[x][0] ] * add[x];
- sum[ ch[x][1] ] += (long long)sz[ ch[x][1] ] * add[x];
- add[x] = 0;
- }
- }
- //把孩子状态更新上来
- inline void push_up(int x) {
- sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
- /*这是题目特定函数*/
- sum[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
- }
- /*初始化*/
- inline void makeTree(int &x,int l,int r,int f) {
- if(l > r) return ;
- int m = (l + r)>>1;
- NewNode(x , num[m]); /*num[m]权值改成题目所需的*/
- makeTree(ch[x][0] , l , m - 1 , x);
- makeTree(ch[x][1] , m + 1 , r , x);
- pre[x] = f;
- push_up(x);
- }
- inline void init(int n) {/*这是题目特定函数*/
- ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
- add[0] = sum[0] = 0;
- root = top1 = 0;
- //为了方便处理边界,加两个边界顶点
- NewNode(root , -1);
- NewNode(ch[root][1] , -1);
- pre[top1] = root;
- sz[root] = 2;
- for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]);
- makeTree(keyTree , 0 , n-1 , ch[root][1]);
- push_up(ch[root][1]);
- push_up(root);
- }
- /*更新*/
- inline void update( ) {/*这是题目特定函数*/
- int l , r , c;
- scanf("%d%d%d",&l,&r,&c);
- RotateTo(l-1,0);
- RotateTo(r+1,root);
- add[ keyTree ] += c;
- sum[ keyTree ] += (long long)c * sz[ keyTree ];
- }
- /*询问*/
- inline void query() {/*这是题目特定函数*/
- int l , r;
- scanf("%d%d",&l,&r);
- RotateTo(l-1 , 0);
- RotateTo(r+1 , root);
- printf("%lld\n",sum[keyTree]);
- }
- /*这是题目特定变量*/
- int num[maxn];
- int val[maxn];
- int add[maxn];
- long long sum[maxn];
- }spt;
- int main() {
- int n , m;
- scanf("%d%d",&n,&m);
- spt.init(n);
- while(m --) {
- char op[2];
- scanf("%s",op);
- if(op[0] == 'Q') {
- spt.query();
- } else {
- spt.update();
- }
- }
- return 0;
- }
7:动态树
8:斯坦纳树
9:主席树
10:QTree