BZOJ 2631: tree [LCT splay区间]
2631: tree
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 3854 Solved: 1292
[Submit][Status][Discuss]
Description
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
HINT
数据规模和约定
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4
煞笔错误,毁我青春
把i打成x
标记和维护序列一样,只不过这次用splay而已 http://www.cnblogs.com/candy99/p/5951198.html
提取链直接写了个split,和splay的区间操作很像哈
然后usigned int即可
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define pa t[x].fa #define lc t[x].ch[0] #define rc t[x].ch[1] const int N=1e5+5,MOD=51061; typedef unsigned int ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } struct node{ int ch[2],fa,rev,size; ll sum,w,add,mul; node():add(0),mul(1){} }t[N]; inline int wh(int x){return t[pa].ch[1]==x;} inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;} inline void update(int x){ t[x].sum=(t[lc].sum+t[rc].sum+t[x].w)%MOD; t[x].size=(t[lc].size+t[rc].size+1)%MOD; } inline void paint(int x,ll d,ll v){//printf("paint %d %d %d\n",x,d,v); t[x].add=(t[x].add*v+d)%MOD; t[x].mul=(t[x].mul*v)%MOD; t[x].w=(t[x].w*v+d)%MOD; t[x].sum=(t[x].sum*v+d*t[x].size)%MOD;//printf("sum %d\n",t[x].sum); } inline void pushDown(int x){ if(t[x].rev){ t[lc].rev^=1; t[rc].rev^=1; swap(lc,rc); t[x].rev=0; } if(t[x].add||t[x].mul!=1){ paint(lc,t[x].add,t[x].mul); paint(rc,t[x].add,t[x].mul); t[x].add=0; t[x].mul=1; } } inline void rotate(int x){ int f=t[x].fa,g=t[f].fa,c=wh(x); if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g; t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f; t[x].ch[c^1]=f;t[f].fa=x; update(f);update(x); } int st[N],top; inline void splay(int x){ top=0;st[++top]=x; for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa; for(int i=top;i>=1;i--) pushDown(st[i]); for(;!isRoot(x);rotate(x)) if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x); } inline void Access(int x){ for(int y=0;x;y=x,x=pa){ splay(x); rc=y; update(x); } } inline void MakeRoot(int x){ Access(x);splay(x); t[x].rev^=1; } inline int FindRoot(int x){ Access(x);splay(x); while(lc) x=lc; return x; } inline void Link(int x,int y){ MakeRoot(x); t[x].fa=y; } inline void Cut(int x,int y){ MakeRoot(x); Access(y);splay(y); t[y].ch[0]=t[x].fa=0; } inline void split(int x,int y){ MakeRoot(x);Access(y);splay(y); } int n,Q,op,x,y,c; char s[3]; int main(){ //freopen("in.txt","r",stdin); n=read();Q=read(); for(int i=1;i<=n-1;i++) x=read(),y=read(),Link(x,y),t[i].size=t[i].w=t[i].sum=1; t[n].size=t[n].w=t[n].sum=1; while(Q--){ scanf("%s",s); x=read();y=read(); if(s[0]=='+') c=read(),split(x,y),paint(y,c,1); if(s[0]=='-'){ Cut(x,y); x=read();y=read(); Link(x,y); } if(s[0]=='*') c=read(),split(x,y),paint(y,0,c); if(s[0]=='/') split(x,y),printf("%d\n",t[y].sum); } }
Copyright:http://www.cnblogs.com/candy99/