• COJ 0981 WZJ的数据结构(负十九)树综合


    WZJ的数据结构(负十九)
    难度级别:E; 运行时间限制:3500ms; 运行空间限制:262144KB; 代码长度限制:2000000B
    试题描述

    WZJ的数据结构中有很多都是关于树的。这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去:

    WZJ:为了大家简单,我规定一开始是一棵有根树。

    LZJ:那我一定得加上换根操作喽。

    XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做。

    CHX:子树信息修改,子树信息增加,子树信息翻倍,维护子树信息的最大,最小,总和肯定也很好做。

    WZJ:那这道题太水了吧,我们要能随时改变树的形态多好,加个换父亲的操作吧。

    CHX:那也够水的,咱们再加一个查询父亲的操作吧。

    LZJ:好不容易出了一道综合题,再加一个查询是否在子树内的操作吧。

    XJR:一定要卡掉离线是必须的吧?

    输入
    本题一共有22个操作:
    第一行是N和M,表示有这棵树有N个点M个询问
    然后是N-1行,每行x,y表示x-y有一条边
    接下去是N行,每行是一个数字,表示每个点的权值
    后面一行表示根
    接下来是M行
    第一个数字是K
    K=0 表示换根,后面x,表示把这棵树的根变成x
    K=1 表示点修改,后面x,y 表示把点x的权值改为y
    K=2 表示点增加,后面x,y 表示把点x的权值增加y
    K=3 表示点翻倍,后面x,y 表示把点x的权值翻y倍
    K=4 表示点询问权值,后面x 表示询问这个点的权值
    K=5 表示链修改,后面x,y,z,表示把这棵树中x-y的路径上点权值改成z
    K=6 表示链增加,后面x,y,z,表示把这棵树中x-y的路径上点权值增加z
    K=7 表示链翻倍,后面x,y,z,表示把这棵树中x-y的路径上点权值翻z倍
    K=8 表示链询问min,后面x,y,表示询问这棵树中x-y的路径上点的min
    K=9 表示链询问max,后面x,y,表示询问这棵树中x-y的路径上点的max
    K=10 表示链询问sum,后面x,y,表示询问这棵树中x-y的路径上点的sum
    K=11 表示链询问siz,后面x,y,表示询问这棵树中x-y的路径上点的多少
    K=12 表示子树修改,后面x,y,表示以x为根的子树的点权值改成y
    K=13 表示子树增加,后面x,y,表示以x为根的子树的点权值增加y
    K=14 表示子树翻倍,后面x,y,表示以x为根的子树的点权值翻y倍
    K=15 表示子树询问min,后面x,表示询问以x为根的子树的点的min
    K=16 表示子树询问max,后面x,表示询问以x为根的子树的点的max
    K=17 表示子树询问sum,后面x,表示询问以x为根的子树的点的sum
    K=18 表示子树询问siz,后面x,表示询问以x为根的子树的点的多少
    K=19 表示换父亲,后面x,y,表示把x的父亲换成y,如果y在x子树里不操作
    K=20 表示询问子树,后面x,y, 表示询问y是否在x的子树内,输出true/false
    K=21 表示查询父亲,后面x,表示询问x的父亲的点权值,若没有父亲则输出-1
    输出
    对于每个询问输出一个答案,一行一个。
    输入示例
    5 30
    1 2
    2 3
    3 4
    4 5
    1 -2 3 -1 2
    3
    0 2
    1 2 2
    2 3 1
    3 5 5
    4 2
    5 3 2 5
    6 1 4 3
    7 4 5 2
    8 5 3
    9 2 5
    10 1 5
    11 3 4
    12 4 -3
    13 2 -1
    14 3 4
    15 2
    16 2
    17 4
    18 4
    19 4 1
    20 1 4
    21 1
    14 1 4
    15 3
    18 1
    19 5 3
    21 5
    13 3 1
    4 5
    17 2
    输出示例
    2
    4
    20
    44
    2
    -16
    28
    -32
    2
    true
    7
    28
    3
    28
    -63
    -79
    其他说明
    N,M<=100000,所有计算结果保证在long long范围之内。

    题解:水水哒AAA树全都搞定啦。(我如果把switch改成二分查找会不会快一点呢哈哈)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cstring>
      7 #define PAU putchar(' ')
      8 #define ENT putchar('
    ')
      9 #define CH for(int d=0;d<=1;d++) if(ch[d])
     10 using namespace std;
     11 const int maxn=100000+10,inf=1<<29;
     12 struct info{long long mi,mx,siz,sm;}null=(info){inf,-inf,0,0};
     13 struct tag{int mul,add;bool empty(){return (mul==1&&add==0);}}nulltag=(tag){1,0};
     14 info operator+(const info&a,const info&b){
     15     return (info){min(a.mi,b.mi),max(a.mx,b.mx),a.siz+b.siz,a.sm+b.sm};
     16 }
     17 info operator+(const info&a,const tag&b){
     18     return a.siz?(info){a.mi*b.mul+b.add,a.mx*b.mul+b.add,a.siz,a.sm*b.mul+b.add*a.siz}:null;
     19 }
     20 tag operator+(const tag&a,const tag&b){
     21     return (tag){a.mul*b.mul,a.add*b.mul+b.add};
     22 }
     23 struct snode{
     24     snode*ch[2],*fa;
     25     info x,sm;tag od,all;
     26     void init(){x=sm=null;od=all=nulltag;ch[0]=ch[1]=fa=NULL;return;}
     27     snode(){x=sm=null;od=all=nulltag;ch[0]=ch[1]=fa=NULL;}
     28     void addt(tag a){
     29         od=od+a;all=all+a;x=x+a;sm=sm+a;return;
     30     }
     31     void down(){
     32         if(!od.empty()){CH{ch[d]->addt(od);};od=nulltag;}return;
     33     }
     34     void update(){
     35         sm=x;CH{sm=sm+ch[d]->sm;}return;
     36     }
     37 }Splay[maxn],*root[maxn];
     38 int parent(snode*x,snode*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
     39 static void rotate(snode*x){
     40     snode*y,*z;int d1=parent(x,y),d2=parent(y,z);
     41     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
     42     y->fa=x;x->fa=z;x->ch[d1^1]=y;
     43     if(d2!=-1) z->ch[d2]=x;
     44     y->update();return;
     45 }
     46 void pushdown(snode*x){
     47     static snode*s[maxn];int top=0;
     48     for(snode*y;;x=y){
     49         s[top++]=x;y=x->fa;
     50         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
     51     } while(top--) s[top]->down();return;
     52 }
     53 static snode*splay(snode*x){
     54     pushdown(x);snode*y,*z;int d1,d2;
     55     while(true){
     56         if((d1=parent(x,y))<0) break;
     57         if((d2=parent(y,z))<0){rotate(x);break;}
     58         if(d1==d2) rotate(y),rotate(x);
     59         else rotate(x),rotate(x);
     60     } x->update();return x;
     61 }
     62 snode*join(snode*x,snode*y){
     63     if(!x)return y;if(!y)return x;
     64     while(x->ch[1]) x->down(),x=x->ch[1];
     65     splay(x)->ch[1]=y;y->fa=x;x->update();return x;
     66 }
     67 struct node{
     68     node*ch[2],*fa,*s[2];
     69     info x,sm,sb,all;tag cha,tre;bool rev;
     70     int id;
     71     void revt(){
     72         swap(ch[0],ch[1]);swap(s[0],s[1]);rev^=1;return;
     73     }
     74     void chat(tag a){
     75         x=x+a;sm=sm+a;cha=cha+a;all=sm+sb;return;
     76     }
     77     void tret(tag a){
     78         tre=tre+a;sb=sb+a;all=sm+sb;if(root[id])root[id]->addt(a);return;
     79     }
     80     void down(){
     81         if(rev){CH{ch[d]->revt();}rev=false;}
     82         if(!cha.empty()){CH{ch[d]->chat(cha);}cha=nulltag;}
     83         if(!tre.empty()){CH{ch[d]->tret(tre);}tre=nulltag;}
     84         return;
     85     }
     86     void update(){
     87         sm=x;sb=null;
     88         if(root[id])sb=sb+root[id]->sm;
     89         CH{sm=sm+ch[d]->sm;sb=sb+ch[d]->sb;}
     90         all=sm+sb;
     91         s[0]=ch[0]?ch[0]->s[0]:this;
     92         s[1]=ch[1]?ch[1]->s[1]:this;
     93         return;
     94     }
     95 }lct[maxn];
     96 int parent(node*x,node*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
     97 void rotate(node*x){
     98     node*y,*z;int d1=parent(x,y),d2=parent(y,z);
     99     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
    100     y->fa=x;x->fa=z;x->ch[d1^1]=y;
    101     if(d2!=-1) z->ch[d2]=x;
    102     y->update();return;
    103 }
    104 void pushdown(node*x){
    105     static node*s[maxn];int top=0;
    106     for(node*y;;x=y){
    107         s[top++]=x;y=x->fa;
    108         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
    109     } while(top--) s[top]->down();return;
    110 }
    111 node*splay(node*x){
    112     pushdown(x);node*y,*z;int d1,d2;
    113     while(true){
    114         if((d1=parent(x,y))<0) break;
    115         if((d2=parent(y,z))<0){rotate(x);break;}
    116         if(d1==d2) rotate(y),rotate(x);
    117         else rotate(x),rotate(x);
    118     } x->update();return x;
    119 }
    120 void add(snode*x,snode*&y,info tag){
    121     x->init();x->x=tag;x->ch[0]=y;if(y)y->fa=x;x->update();y=x;return;
    122 }
    123 void detach(node*x){
    124     add(x->ch[1]->s[0]->id+Splay,root[x->id],x->ch[1]->all);return;
    125 }
    126 void connect(node*x,node*y){
    127     snode*p=y->s[0]->id+Splay;splay(p);
    128     if(p->ch[0]) p->ch[0]->fa=NULL;
    129     if(p->ch[1]) p->ch[1]->fa=NULL;
    130     root[x->id]=join(p->ch[0],p->ch[1]);
    131     y->chat(p->all);y->tret(p->all);return;
    132 }
    133 node*access(node*x){
    134     node*ret=NULL;
    135     for(;x;x=x->fa){
    136         if(splay(x)->ch[1]) detach(x);
    137         if(x->ch[1]=ret) connect(x,ret);
    138         (ret=x)->update();
    139     } return ret;
    140 }
    141 void makeroot(int x){access(x+lct)->revt();return;}
    142 void link(int x,int y){
    143     access(lct+y);splay(lct+y)->ch[1]=lct+x;makeroot(x);splay(lct+x)->fa=lct+y;return;
    144 }
    145 node*findfa(node*x){
    146     x=splay(x)->ch[0];
    147     if(!x) return x;
    148     else return x->s[1];
    149 }
    150 int queryfa(int x){
    151     node*t;access(x+lct);
    152     if(!(t=findfa(x+lct))) return -1;
    153     else return t->x.sm;
    154 }
    155 int treeroot;
    156 node*findtop(node*x){return splay(x)->s[0];}
    157 bool insub(int x,int y){
    158     if(x==y||x==treeroot) return true;
    159     access(y+lct);if(findtop(x+lct)==findtop(y+lct)) return true;
    160     return false;
    161 }
    162 void changesub(int x,int y,tag t){
    163     makeroot(x);access(lct+y);splay(lct+y);
    164     lct[y].x=lct[y].x+t;
    165     if(root[y]) root[y]->addt(t);
    166     lct[y].update();return;
    167 }
    168 void changecha(int x,int y,tag t){
    169     makeroot(x);access(lct+y)->chat(t);return;
    170 }
    171 info querycha(int x,int y){
    172     makeroot(x);return access(lct+y)->sm;
    173 }
    174 info querysub(int x,int y){
    175     makeroot(x);access(lct+y);splay(lct+y);return root[y]?lct[y].x+root[y]->sm:lct[y].x;
    176 }
    177 void cutfa(int x){
    178     node*t=(access(lct+x),splay(lct+x));
    179     t->ch[0]=t->ch[0]->fa=NULL;t->update();return;
    180 }
    181 void linkfa(int x,int fa){
    182     access(fa+lct);splay(lct+fa);makeroot(x);splay(lct+x)->fa=lct+fa;lct[fa].update();
    183     add(Splay+x,root[fa],lct[x].all);
    184     return;
    185 }
    186 void splitfa(int r,int x,int fa){
    187     makeroot(r);if((access(lct+x),access(lct+fa))==lct+x) return;
    188     cutfa(x);linkfa(x,fa);return;
    189 }
    190 int n,Q,p1[maxn],p2[maxn],A[maxn];
    191 void inittree(int*a){
    192     for(int i=1;i<=n;i++){
    193         lct[i].id=i;
    194         lct[i].s[0]=lct[i].s[1]=lct+i;
    195         lct[i].x=lct[i].sm=lct[i].all=(info){a[i],a[i],1,a[i]};
    196         lct[i].cha=lct[i].tre=nulltag;
    197     } return;
    198 }
    199 inline int read(){
    200     int x=0,sig=1;char ch=getchar();
    201     while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();}
    202     while(isdigit(ch))x=10*x+ch-'0',ch=getchar();
    203     return x*=sig;
    204 }
    205 inline void write(long long x){
    206     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
    207     int len=0;static long long buf[20];while(x)buf[len++]=x%10,x/=10;
    208     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
    209 }
    210 void init(){
    211     n=read();Q=read();
    212     for(int i=2;i<=n;i++) p1[i]=read(),p2[i]=read();
    213     for(int i=1;i<=n;i++) A[i]=read();
    214     inittree(A);
    215     for(int i=2;i<=n;i++) link(p1[i],p2[i]);
    216     treeroot=read();makeroot(treeroot);
    217     return;
    218 }
    219 void work(){
    220     int x,y,z,tp;
    221     while(Q--){
    222         tp=read();x=read();
    223         switch(tp){
    224             case 0:
    225                 makeroot(x),treeroot=x;
    226                 break;
    227             case 1:
    228                 changecha(x,x,(tag){0,read()});
    229                 break;
    230             case 2:
    231                 changecha(x,x,(tag){1,read()});
    232                 break;
    233             case 3:
    234                 changecha(x,x,(tag){read(),0});
    235                 break;
    236             case 4:
    237                 write(querycha(x,x).mi);ENT;
    238                 break;
    239             case 5:
    240                 y=read();changecha(x,y,(tag){0,read()});
    241                 break;
    242             case 6:
    243                 y=read();changecha(x,y,(tag){1,read()});
    244                 break;
    245             case 7:
    246                 y=read();changecha(x,y,(tag){read(),0});
    247                 break;
    248             case 8:
    249                 y=read();write(querycha(x,y).mi);ENT;
    250                 break;
    251             case 9:
    252                 y=read();write(querycha(x,y).mx);ENT;
    253                 break;
    254             case 10:
    255                 y=read();write(querycha(x,y).sm);ENT;
    256                 break;
    257             case 11:
    258                 y=read();write(querycha(x,y).siz);ENT;
    259                 break;
    260             case 12:
    261                 changesub(treeroot,x,(tag){0,read()});
    262                 break;
    263             case 13:
    264                 changesub(treeroot,x,(tag){1,read()});
    265                 break;
    266             case 14:
    267                 changesub(treeroot,x,(tag){read(),0});
    268                 break;
    269             case 15:
    270                 write(querysub(treeroot,x).mi);ENT;
    271                 break;
    272             case 16:
    273                 write(querysub(treeroot,x).mx);ENT;
    274                 break;
    275             case 17:
    276                 write(querysub(treeroot,x).sm);ENT;
    277                 break;
    278             case 18:
    279                 write(querysub(treeroot,x).siz);ENT;
    280                 break;
    281             case 19:
    282                 y=read();splitfa(treeroot,x,y);
    283                 break;
    284             case 20:
    285                 y=read();if(insub(x,y)) puts("true");else puts("false");
    286                 break;
    287             case 21:
    288                 write(queryfa(x));ENT;
    289                 break;
    290         }
    291     }
    292     return;
    293 }
    294 void print(){
    295     return;
    296 }
    297 int main(){init();work();print();return 0;}
  • 相关阅读:
    C++ 内置宏定义 与 预编译指令
    C++ 反射机制的简单实现
    Intellij打包jar文件,“java.lang.SecurityException: Invalid signature file digest for Manifest main attrib
    IntelliJ IDEA 运行你的第一个Java应用程序 idea运行main方法
    IDEA重新打jar包时报错MANIFEST.MF already exists in VFS
    在 RPA10.X 运行异常,RPA9 却正常的问题处理
    Python判断文件是否存在的三种方法
    Python日期时间函数
    Chrome提示:"请停用以开发者模式运行的扩展程序"的解决办法
    Win10提示“无法打开此计算机上的组策略对象”如何解决
  • 原文地址:https://www.cnblogs.com/chxer/p/4592545.html
Copyright © 2020-2023  润新知