Poj3468-A Simple Problem with Integers(伸展树练练手)
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
题意: 给出N个数,有两种操作
Q a b 查询[a,b]区间的和
C a b c [a,b]区间所有值加上c
解析:成段更新问题,线段树已经可以做,我试着用伸展树做做。
代码:
//这题用线段树就可以做了,拿来用伸展树练练手 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; typedef long long LL; const int maxn=100005; int A[maxn],cnt; //A数组保存数,cnt是节点标号,我是用数组模拟的 struct treap { treap* son[2]; //左右儿子 int s; LL v,add,sum; treap(){ s=v=add=sum=0; son[0]=son[1]=NULL; } treap(LL nv); int rk(){ return son[0]->s+1; } //排名,第几个数 int cmp(int k) //比较,如果相等返回-1,小于返回0,大于1 { if(k==rk()) return -1; return k<rk()?0:1; } void Set(LL d) { v+=d; add+=d; sum+=d*s; } void pushup() { s=son[0]->s+son[1]->s+1; sum=son[0]->sum+son[1]->sum+v; } void pushdown() //处理懒惰标记 { if(add!=0) { son[0]->Set(add); son[1]->Set(add); add=0; } } }null,tr[maxn]; treap::treap(LL nv) { sum=v=nv; s=1; add=0; son[0]=son[1]=&null; } treap* NewNode(LL x) { tr[cnt]=treap(x); return tr+cnt++; } struct splaytree { int Size; treap* root; splaytree(){ Size=0; root=&null; } void Rotate(treap* &t,int d) //翻转操作 { t->pushdown(); treap* p=t->son[d^1]; p->pushdown(); t->son[d^1]=p->son[d]; p->son[d]=t; t->pushup(); t=p; t->pushup(); } void Splay(treap* &t,int k) //将第k大的节点伸展到根 { t->pushdown(); int d=t->cmp(k); if(d!=-1) { if(d) Splay(t->son[d],k- t->rk()); else Splay(t->son[d],k); Rotate(t,d^1); } } void Build(treap* &t,int le,int ri) //将N个数建成一棵树 { if(le>ri) return; int mid=(le+ri)/2; t=NewNode(A[mid]); Build(t->son[0],le,mid-1); Build(t->son[1],mid+1,ri); t->pushup(); } LL Query(treap* &t,int x,int y) { LL ret=0; Splay(t,y); ret+=t->son[0]->sum+t->v; if(x>1) { Splay(t,x-1); ret-=t->son[0]->sum+t->v; } return ret; } void Add(treap* &t,int x,int y,int add) { Splay(t,y); t->v+=add; t->sum+=add*y; t->son[0]->Set(add); if(x>1) { Splay(t,x-1); t->v-=add; t->sum-=add*(x-1); t->son[0]->Set(-add); } } }; int main() { int N,Q; while(scanf("%d%d",&N,&Q)!=EOF) { for(int i=1;i<=N;i++) scanf("%d",&A[i]); splaytree spt; cnt=0; spt.Build(spt.root,1,N); int x,y,d; char op[3]; while(Q--) { scanf("%s",op); if(op[0]=='Q') { scanf("%d%d",&x,&y); printf("%lld\n",spt.Query(spt.root,x,y)); } else { scanf("%d%d%d",&x,&y,&d); spt.Add(spt.root,x,y,d); } } } return 0; }