bzoj3159: 决战
Description
Input
第一行有三个整数N、M和R,分别表示树的节点数、指令和询问总数,以及X国的据点。
接下来N-1行,每行两个整数X和Y,表示Katharon国的一条道路。
接下来M行,每行描述一个指令或询问,格式见题目描述。
Output
对于每个询问操作,输出所求的值。
Sample Input
5 8 1
1 2
2 3
3 4
4 5
Sum 2 4
Increase 3 5 3
Minor 1 4
Sum 4 5
Invert 1 3
Major 1 2
Increase 1 5 2
Sum 1 5
1 2
2 3
3 4
4 5
Sum 2 4
Increase 3 5 3
Minor 1 4
Sum 4 5
Invert 1 3
Major 1 2
Increase 1 5 2
Sum 1 5
Sample Output
0
0
6
3
19
0
6
3
19
HINT
1<=N,M<=50000.且对于运送操作1<=W<=1000
Source
题解:
有两种做法:第一种是用两个平衡树,一个用来维护形态(即lct)另一个用来维护每条实链(实边构成的链)的权值
另一种是利用操作的性质,用树链剖分+treep来作
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 11 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 12 if (ok) x=-x; 13 } 14 const int maxn=50005; 15 typedef long long int64; 16 char s[10]; 17 int n,q,r,x,y,v; 18 int random(int lim){return rand()%lim+1;} 19 typedef pair<int,int> PII; 20 struct node{ 21 int siz; 22 int64 val,maxv,minv,sum; 23 void add(int64 v){val+=v,maxv+=v,minv+=v,sum+=v*siz;} 24 void init(){maxv=minv=sum=val,siz=1;} 25 void update(const node &x){siz+=x.siz,maxv=max(maxv,x.maxv),minv=min(minv,x.minv),sum+=x.sum;} 26 }; 27 struct treep{ 28 node p[maxn]; 29 int son[maxn][2],rev[maxn],add[maxn]; 30 void reverse(int x){if (x) rev[x]^=1;} 31 void addtag(int x,int64 v){if (x) add[x]+=v,p[x].add(v);} 32 void pushdown(int x){ 33 if (rev[x]) swap(son[x][0],son[x][1]),reverse(son[x][0]),reverse(son[x][1]),rev[x]=0; 34 if (add[x]) addtag(son[x][0],add[x]),addtag(son[x][1],add[x]),add[x]=0; 35 } 36 void update(int x){ 37 p[x].init(); 38 if (son[x][0]) p[x].update(p[son[x][0]]); 39 if (son[x][1]) p[x].update(p[son[x][1]]); 40 } 41 PII split(int x,int k){ 42 if (!k) return make_pair(0,x); 43 if (p[x].siz==k) return make_pair(x,0); 44 PII tmp; pushdown(x); 45 if (k<=p[son[x][0]].siz){ 46 tmp=split(son[x][0],k),son[x][0]=tmp.second,update(x); 47 return make_pair(tmp.first,x); 48 } 49 else{ 50 tmp=split(son[x][1],k-p[son[x][0]].siz-1),son[x][1]=tmp.first,update(x); 51 return make_pair(x,tmp.second); 52 } 53 } 54 int merge(int x,int y){ 55 if (!x||!y) return x+y; 56 pushdown(x),pushdown(y); 57 if (random(p[x].siz+p[y].siz)<=p[x].siz){ 58 son[x][1]=merge(son[x][1],y),update(x); 59 return x; 60 } 61 else{ 62 son[y][0]=merge(x,son[y][0]),update(y); 63 return y; 64 } 65 } 66 }T; 67 struct LCT{ 68 int fa[maxn],son[maxn][2],root[maxn],rev[maxn],siz[maxn]; 69 void init(int n){for (int i=1;i<=n;i++) root[i]=i;} 70 int which(int x){return son[fa[x]][1]==x;} 71 bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;} 72 void reverse(int x){rev[x]^=1;} 73 void pushdown(int x){if (rev[x]) swap(son[x][0],son[x][1]),reverse(son[x][0]),reverse(son[x][1]),rev[x]=0;} 74 void relax(int x){if (!isroot(x)) relax(fa[x]); pushdown(x);} 75 void update(int x){ 76 siz[x]=1; 77 if (son[x][0]) siz[x]+=siz[son[x][0]]; 78 if (son[x][1]) siz[x]+=siz[son[x][1]]; 79 } 80 void rotate(int x){ 81 int y=fa[x],z=fa[y],d=which(x),dd=which(y); 82 fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=fa[y]; 83 if (!isroot(y)) son[z][dd]=x; 84 son[x][d^1]=y,fa[y]=x,update(y),update(x); 85 } 86 void splay(int x){ 87 relax(x); 88 int t; 89 for (t=x;!isroot(t);t=fa[t]); 90 swap(root[t],root[x]); 91 while (!isroot(x)){ 92 if (isroot(fa[x])) rotate(x); 93 else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x); 94 else rotate(x),rotate(x); 95 } 96 } 97 void access(int x){ 98 for (int p=0;x;x=fa[x]){ 99 splay(x); 100 if (son[x][1]){ 101 PII tmp=T.split(root[x],siz[son[x][0]]+1); 102 root[x]=tmp.first,root[son[x][1]]=tmp.second; 103 } 104 if (p) root[x]=T.merge(root[x],root[p]),root[p]=0; 105 son[x][1]=p,fa[p]=x,update(p=x); 106 } 107 } 108 void make_root(int x){access(x),splay(x),reverse(x),T.reverse(root[x]);} 109 void link(int x,int y){make_root(x),fa[x]=y;} 110 void reverse(int x,int y){make_root(x),access(y),splay(y),T.reverse(root[y]);} 111 void addtag(int x,int y,int v){make_root(x),access(y),splay(y),T.addtag(root[y],v);} 112 int64 query_max(int x,int y){make_root(x),access(y),splay(y);return T.p[root[y]].maxv;} 113 int64 query_min(int x,int y){make_root(x),access(y),splay(y);return T.p[root[y]].minv;} 114 int64 query_sum(int x,int y){make_root(x),access(y),splay(y);return T.p[root[y]].sum;} 115 }lct; 116 int main(){ 117 srand('f'+'u'+'c'+'k'); 118 read(n),read(q),read(r),lct.init(n); 119 for (int i=1;i<=n;i++) T.p[i].val=0,T.p[i].init(); 120 for (int i=1;i<n;i++) read(x),read(y),lct.link(x,y); 121 while (q--){ 122 scanf("%s",s),read(x),read(y); 123 if (s[2]=='c') read(v),lct.addtag(x,y,v); 124 else if (s[2]=='m') printf("%lld\n",lct.query_sum(x,y)); 125 else if (s[2]=='j') printf("%lld\n",lct.query_max(x,y)); 126 else if (s[2]=='n') printf("%lld\n",lct.query_min(x,y)); 127 else if (s[2]=='v') lct.reverse(x,y); 128 } 129 return 0; 130 }