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改成二分查找会不会快一点呢哈哈)
#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的数据结构(负十九)树综合的更多相关文章
- COJ 1010 WZJ的数据结构(十) 线段树区间操作
传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: ...
- js上 十九、综合案例
十九.综合案例 题目一: 封装一个函数equal(a1,a2),传入两个一维数组,判断两个数组是否包含相同的元素,如果相等,函数的返回值为true, 不相等,函数的返回值为false 1)例:arr1 ...
- COJ 0970 WZJ的数据结构(负三十)树分治
WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...
- COJ 0990 WZJ的数据结构(负十)
WZJ的数据结构(负十) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 给你一个N个节点的有根树,从1到N编号,根节点为1并给 ...
- COJ 0967 WZJ的数据结构(负三十三)
WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大 ...
- COJ 0995 WZJ的数据结构(负五)区间操作
WZJ的数据结构(负五) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为 ...
- COJ 0999 WZJ的数据结构(负一)
WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T ...
- COJ 0979 WZJ的数据结构(负二十一)
WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个 ...
- COJ 1008 WZJ的数据结构(八) 树上操作
传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=986 WZJ的数据结构(八) 难度级别:E: 运行时间限制:3000ms: ...
随机推荐
- 用MFC完成一个简单的猜数字游戏: 输入的四位数中,位置和数字都正确为A,数字相同而位置不同的为B。
最近学习了MFC一些比较基础的知识,所以打算通过做一个简单的数字游戏来理解MFC的流程并进一步熟悉其操作. 在这里,我做了一个猜数字的小游戏.第一步当然是设计主界面,先给大家展示一下游戏界面: 主界面 ...
- 有限状态机FSM(自动售报机Verilog实现)
有限状态机FSM(自动售报机Verilog实现) FSM 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法. 状态机有两大类:Mealy型和Moore型. Moore型状态机的输出只与当前状态有 ...
- ViewPager的setOnPageChangeListener方法详解
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=548173 ViewPage使用时,最关键的代码就是setOnPageChang ...
- Android BaseAdapter Gallery 画廊视图 (左右拖动图片列表拖至中间时图片放大显示)
画廊视图使用Gallery表示,能够按水平方向显示内容,并且可以手指直接拖动图片和移动,一般用来浏览图片,,被选中的选项位于中间,并且可以响应事件显示信息.在使用画廊视图时,首先在屏幕上添加Galle ...
- 阅读underscore源码笔记
本文为原创作品,可以转载,但请添加本文连接,谢谢传阅,本人博客已转移至github,地址为:jruif.github.io underscorejs,一个实用的的Javascript函数库,值得推荐, ...
- nginx中时间的管理
nginx出于性能考虑採用类似lib_event的方式,自己对时间进行了cache,用来降低对gettimeofday()的调用,由于一般来说server对时间的精度要求不是特别的高,只是假设须要比較 ...
- 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
手把手叫你玩转网络编程系列之三 完毕port(Completion Port)具体解释 ...
- cache 的设计与实现--转载
本文整理自一下两篇博客:http://my.oschina.net/ScottYang/blog/298727http://my.oschina.net/u/866190/blog/188712 Ca ...
- Because the people who are crazy enough to think they can change the world, are the ones who do.
Here's to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the square h ...
- AS 断点调试 debug
debug面板 点击下图工具栏开启调试会话 此种调试方式是通过冻结应用运行的状态,仿佛时间停止了一般,然后我们逐一观察此时程序的各个参数是否符合我们的预期. 这种调试方法适用于对时间不敏感的程序.也就 ...