zoukankan      html  css  js  c++  java
  • 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
    ",lct.query_sum(x,y));
    125         else if (s[2]=='j') printf("%lld
    ",lct.query_max(x,y));
    126         else if (s[2]=='n') printf("%lld
    ",lct.query_min(x,y));
    127         else if (s[2]=='v') lct.reverse(x,y);
    128     }
    129     return 0;
    130 }
  • 相关阅读:
    jq绑定on事件无效
    数字以0补全
    redis常用操作
    mysql数据操作日常
    centos端口映射
    centos7防火墙操作
    mysql5.7order by问题
    centos无法上网解决方法
    面试题
    ztree 获取子节点所有父节点的name的拼接
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5224858.html
Copyright © 2011-2022 走看看