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

Sample Output

0

0

6

3

19

HINT

 

1<=N,M<=50000.且对于运送操作1<=W<=1000

 

Source

Katharon+#1

 

题解:

有两种做法:第一种是用两个平衡树,一个用来维护形态(即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 }

 

posted @ 2016-02-28 15:36  chenyushuo  阅读(640)  评论(0编辑  收藏  举报