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改成二分查找会不会快一点呢哈哈)

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
#define CH for(int d=0;d<=1;d++) if(ch[d])
using namespace std;
const int maxn=+,inf=<<;
struct info{long long mi,mx,siz,sm;}null=(info){inf,-inf,,};
struct tag{int mul,add;bool empty(){return (mul==&&add==);}}nulltag=(tag){,};
info operator+(const info&a,const info&b){
return (info){min(a.mi,b.mi),max(a.mx,b.mx),a.siz+b.siz,a.sm+b.sm};
}
info operator+(const info&a,const tag&b){
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;
}
tag operator+(const tag&a,const tag&b){
return (tag){a.mul*b.mul,a.add*b.mul+b.add};
}
struct snode{
snode*ch[],*fa;
info x,sm;tag od,all;
void init(){x=sm=null;od=all=nulltag;ch[]=ch[]=fa=NULL;return;}
snode(){x=sm=null;od=all=nulltag;ch[]=ch[]=fa=NULL;}
void addt(tag a){
od=od+a;all=all+a;x=x+a;sm=sm+a;return;
}
void down(){
if(!od.empty()){CH{ch[d]->addt(od);};od=nulltag;}return;
}
void update(){
sm=x;CH{sm=sm+ch[d]->sm;}return;
}
}Splay[maxn],*root[maxn];
int parent(snode*x,snode*&y){return (y=x->fa)?y->ch[]==x?:y->ch[]==x?:-:-;}
static void rotate(snode*x){
snode*y,*z;int d1=parent(x,y),d2=parent(y,z);
if(y->ch[d1]=x->ch[d1^]) y->ch[d1]->fa=y;
y->fa=x;x->fa=z;x->ch[d1^]=y;
if(d2!=-) z->ch[d2]=x;
y->update();return;
}
void pushdown(snode*x){
static snode*s[maxn];int top=;
for(snode*y;;x=y){
s[top++]=x;y=x->fa;
if(!y||(y->ch[]!=x&&y->ch[]!=x)) break;
} while(top--) s[top]->down();return;
}
static snode*splay(snode*x){
pushdown(x);snode*y,*z;int d1,d2;
while(true){
if((d1=parent(x,y))<) break;
if((d2=parent(y,z))<){rotate(x);break;}
if(d1==d2) rotate(y),rotate(x);
else rotate(x),rotate(x);
} x->update();return x;
}
snode*join(snode*x,snode*y){
if(!x)return y;if(!y)return x;
while(x->ch[]) x->down(),x=x->ch[];
splay(x)->ch[]=y;y->fa=x;x->update();return x;
}
struct node{
node*ch[],*fa,*s[];
info x,sm,sb,all;tag cha,tre;bool rev;
int id;
void revt(){
swap(ch[],ch[]);swap(s[],s[]);rev^=;return;
}
void chat(tag a){
x=x+a;sm=sm+a;cha=cha+a;all=sm+sb;return;
}
void tret(tag a){
tre=tre+a;sb=sb+a;all=sm+sb;if(root[id])root[id]->addt(a);return;
}
void down(){
if(rev){CH{ch[d]->revt();}rev=false;}
if(!cha.empty()){CH{ch[d]->chat(cha);}cha=nulltag;}
if(!tre.empty()){CH{ch[d]->tret(tre);}tre=nulltag;}
return;
}
void update(){
sm=x;sb=null;
if(root[id])sb=sb+root[id]->sm;
CH{sm=sm+ch[d]->sm;sb=sb+ch[d]->sb;}
all=sm+sb;
s[]=ch[]?ch[]->s[]:this;
s[]=ch[]?ch[]->s[]:this;
return;
}
}lct[maxn];
int parent(node*x,node*&y){return (y=x->fa)?y->ch[]==x?:y->ch[]==x?:-:-;}
void rotate(node*x){
node*y,*z;int d1=parent(x,y),d2=parent(y,z);
if(y->ch[d1]=x->ch[d1^]) y->ch[d1]->fa=y;
y->fa=x;x->fa=z;x->ch[d1^]=y;
if(d2!=-) z->ch[d2]=x;
y->update();return;
}
void pushdown(node*x){
static node*s[maxn];int top=;
for(node*y;;x=y){
s[top++]=x;y=x->fa;
if(!y||(y->ch[]!=x&&y->ch[]!=x)) break;
} while(top--) s[top]->down();return;
}
node*splay(node*x){
pushdown(x);node*y,*z;int d1,d2;
while(true){
if((d1=parent(x,y))<) break;
if((d2=parent(y,z))<){rotate(x);break;}
if(d1==d2) rotate(y),rotate(x);
else rotate(x),rotate(x);
} x->update();return x;
}
void add(snode*x,snode*&y,info tag){
x->init();x->x=tag;x->ch[]=y;if(y)y->fa=x;x->update();y=x;return;
}
void detach(node*x){
add(x->ch[]->s[]->id+Splay,root[x->id],x->ch[]->all);return;
}
void connect(node*x,node*y){
snode*p=y->s[]->id+Splay;splay(p);
if(p->ch[]) p->ch[]->fa=NULL;
if(p->ch[]) p->ch[]->fa=NULL;
root[x->id]=join(p->ch[],p->ch[]);
y->chat(p->all);y->tret(p->all);return;
}
node*access(node*x){
node*ret=NULL;
for(;x;x=x->fa){
if(splay(x)->ch[]) detach(x);
if(x->ch[]=ret) connect(x,ret);
(ret=x)->update();
} return ret;
}
void makeroot(int x){access(x+lct)->revt();return;}
void link(int x,int y){
access(lct+y);splay(lct+y)->ch[]=lct+x;makeroot(x);splay(lct+x)->fa=lct+y;return;
}
node*findfa(node*x){
x=splay(x)->ch[];
if(!x) return x;
else return x->s[];
}
int queryfa(int x){
node*t;access(x+lct);
if(!(t=findfa(x+lct))) return -;
else return t->x.sm;
}
int treeroot;
node*findtop(node*x){return splay(x)->s[];}
bool insub(int x,int y){
if(x==y||x==treeroot) return true;
access(y+lct);if(findtop(x+lct)==findtop(y+lct)) return true;
return false;
}
void changesub(int x,int y,tag t){
makeroot(x);access(lct+y);splay(lct+y);
lct[y].x=lct[y].x+t;
if(root[y]) root[y]->addt(t);
lct[y].update();return;
}
void changecha(int x,int y,tag t){
makeroot(x);access(lct+y)->chat(t);return;
}
info querycha(int x,int y){
makeroot(x);return access(lct+y)->sm;
}
info querysub(int x,int y){
makeroot(x);access(lct+y);splay(lct+y);return root[y]?lct[y].x+root[y]->sm:lct[y].x;
}
void cutfa(int x){
node*t=(access(lct+x),splay(lct+x));
t->ch[]=t->ch[]->fa=NULL;t->update();return;
}
void linkfa(int x,int fa){
access(fa+lct);splay(lct+fa);makeroot(x);splay(lct+x)->fa=lct+fa;lct[fa].update();
add(Splay+x,root[fa],lct[x].all);
return;
}
void splitfa(int r,int x,int fa){
makeroot(r);if((access(lct+x),access(lct+fa))==lct+x) return;
cutfa(x);linkfa(x,fa);return;
}
int n,Q,p1[maxn],p2[maxn],A[maxn];
void inittree(int*a){
for(int i=;i<=n;i++){
lct[i].id=i;
lct[i].s[]=lct[i].s[]=lct+i;
lct[i].x=lct[i].sm=lct[i].all=(info){a[i],a[i],,a[i]};
lct[i].cha=lct[i].tre=nulltag;
} return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(long long x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=;static long long buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
void init(){
n=read();Q=read();
for(int i=;i<=n;i++) p1[i]=read(),p2[i]=read();
for(int i=;i<=n;i++) A[i]=read();
inittree(A);
for(int i=;i<=n;i++) link(p1[i],p2[i]);
treeroot=read();makeroot(treeroot);
return;
}
void work(){
int x,y,z,tp;
while(Q--){
tp=read();x=read();
switch(tp){
case :
makeroot(x),treeroot=x;
break;
case :
changecha(x,x,(tag){,read()});
break;
case :
changecha(x,x,(tag){,read()});
break;
case :
changecha(x,x,(tag){read(),});
break;
case :
write(querycha(x,x).mi);ENT;
break;
case :
y=read();changecha(x,y,(tag){,read()});
break;
case :
y=read();changecha(x,y,(tag){,read()});
break;
case :
y=read();changecha(x,y,(tag){read(),});
break;
case :
y=read();write(querycha(x,y).mi);ENT;
break;
case :
y=read();write(querycha(x,y).mx);ENT;
break;
case :
y=read();write(querycha(x,y).sm);ENT;
break;
case :
y=read();write(querycha(x,y).siz);ENT;
break;
case :
changesub(treeroot,x,(tag){,read()});
break;
case :
changesub(treeroot,x,(tag){,read()});
break;
case :
changesub(treeroot,x,(tag){read(),});
break;
case :
write(querysub(treeroot,x).mi);ENT;
break;
case :
write(querysub(treeroot,x).mx);ENT;
break;
case :
write(querysub(treeroot,x).sm);ENT;
break;
case :
write(querysub(treeroot,x).siz);ENT;
break;
case :
y=read();splitfa(treeroot,x,y);
break;
case :
y=read();if(insub(x,y)) puts("true");else puts("false");
break;
case :
write(queryfa(x));ENT;
break;
}
}
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}

COJ 0981 WZJ的数据结构(负十九)树综合的更多相关文章

  1. COJ 1010 WZJ的数据结构(十) 线段树区间操作

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: ...

  2. js上 十九、综合案例

    十九.综合案例 题目一: 封装一个函数equal(a1,a2),传入两个一维数组,判断两个数组是否包含相同的元素,如果相等,函数的返回值为true, 不相等,函数的返回值为false 1)例:arr1 ...

  3. COJ 0970 WZJ的数据结构(负三十)树分治

    WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...

  4. COJ 0990 WZJ的数据结构(负十)

    WZJ的数据结构(负十) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 给你一个N个节点的有根树,从1到N编号,根节点为1并给 ...

  5. COJ 0967 WZJ的数据结构(负三十三)

    WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大 ...

  6. COJ 0995 WZJ的数据结构(负五)区间操作

    WZJ的数据结构(负五) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为 ...

  7. COJ 0999 WZJ的数据结构(负一)

    WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T ...

  8. COJ 0979 WZJ的数据结构(负二十一)

    WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个 ...

  9. COJ 1008 WZJ的数据结构(八) 树上操作

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=986 WZJ的数据结构(八) 难度级别:E: 运行时间限制:3000ms: ...

随机推荐

  1. 动态规划+滚动数组 -- POJ 1159 Palindrome

    给一字符串,问最少加几个字符能够让它成为回文串. 比方 Ab3bd 最少须要两个字符能够成为回文串 dAb3bAd 思路: 动态规划 DP[i][j] 意味着从 i 到 j 这段字符变为回文串最少要几 ...

  2. 【iOS知识学习】_iOS沙盒机制

    IOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序仅仅能在为该应用创建的目录内读取文件,不能够訪问其它地方的内容.全部的非代码文件都保存在这个地方.比方图片.声音.属性列表和文本文件 ...

  3. 最全的C#图片处理帮助类ImageHelper

    最全的C#图片处理帮助类ImageHelper.cs 方法介绍: 生成缩略图 图片水印处理方法 图片水印位置处理方法 文字水印处理方法 文字水印位置的方法 调整光暗 反色处理 浮雕处理 拉伸图片 滤色 ...

  4. 在top命令下kill和renice进程

    For common process management tasks, top is so great because it gives an overview of the most active ...

  5. 简单dp ---HDU3485 Count 101

    题目大意:让求长度为n的0 和 1 构成的串中不包含101子串的个数有多少. 这个题当时想了好久,以为是一个规律题,一直在推规律,最后还是wa了,上网一看原来是dp问题, 不过确实递推式挺巧妙的. 递 ...

  6. ASP.NET-FineUI开发实践-3

    1.参照模拟数据库分页通过缓存重写内存分页,优化页面响应速度 Grid的响应速度是硬伤,我写了个通用方法把所有数据放在缓存中模拟数据库分页,比自带的缓存分页快很多,这里贴上实体类的通用方法,DataT ...

  7. C#链接远程SQL 服务器方法

     C#链接远程SQL 服务器方法第一步:申请花生壳内网版,要求交1块钱给花生壳服务器做验证.第二步:把你自己主机本地连接那里的内网地址不要自动获取,写成192.168.0.105,子网掩码255.25 ...

  8. Java Criteria表关联查询(两个表未定义关联关系)

    Criteria criteria = this.getSession().createCriteria(Competition.class, "b"); DetachedCrit ...

  9. Eclipse利用代理快速安装插件

    在eclipse启动时增加以下参数: eclipse.exe -vmargs -DproxySet=true -DproxyHost=aProxyAddress -DproxyPort=aProxyP ...

  10. Cacti添加Advance Ping监控模板

    Cacti脚本   1.Advance Ping 脚本及模板   注:要使用此模板,编译PHP时必须加上--enable-sockets选项来支持套接字.   1).功能:此模板用来监控一个TCP/U ...