[bzoj3083][树链剖分][lca]遥远的国度
来源:互联网 发布:工业组态软件 编辑:程序博客网 时间:2024/05/16 15:55
Description
描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。
Input
第1行两个整数n m,代表城市个数和操作数。 第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。 第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1
p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数
id,代表询问以城市id为根的子树中的最小防御值。
Output
对于每个opt=3的操作,输出一行代表对应子树的最小点权值。
Sample Input
3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1
Sample Output
1
2
3
4
HINT
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
题解
其实我一开始看到换根我想用lct的。但是好像这个操作太多了lct常数巨大直接tle
怎么办?很痛苦?来一个树剖筋骨贴
看一看换根的操作,其实换不换根的情况下,树中一个点到另一个点的路径其实是固定的。那么2操作我们可以直接修改
那换根怎么查找??反正肯定不能直接搞对不对。。
设当前询问的是now点,根为id
1、如果id是在原树中以now为根的子树的外面,那么其实是不影响的对不对
2、如果id就是now,那么询问的实质上就变成了整棵树的权
3、如果id在now的子树里面呢?那么实际上就是砍掉了id所在now的那棵子树,然后询问全树的权
拿lca判id在now的哪个部分,如果在now的树里面就倍增求出他在哪棵子树
之后慢慢查找就好了
所以说。。这样就可以水过去了???!!!!
YES!
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f;}struct node{ int x,y,next; }a[411000];int len,last[411000];void ins(int x,int y){ len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len;}int bin[25];int fa[411000][25],tot[411000],son[411000],dep[411000];void pre_tree_node(int x){ tot[x]=1;son[x]=0; for(int i=1;bin[i]<=dep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[x][0]) { fa[y][0]=x; dep[y]=dep[x]+1; pre_tree_node(y); if(tot[son[x]]<tot[y])son[x]=y; tot[x]+=tot[y]; } }}int ys[411000],z,top[411000];void pre_tree_edge(int x,int tp){ ys[x]=++z;top[x]=tp; if(son[x]!=0)pre_tree_edge(son[x],tp); for(int k=last[x];k;k=a[k].next) if(a[k].y!=fa[x][0] && a[k].y!=son[x])pre_tree_edge(a[k].y,a[k].y);}struct trnode{ int lc,rc,l,r,c; int lazy;}tr[411000];int trlen;void bt(int l,int r){ int now=++trlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=-1;tr[now].c=0; tr[now].lazy=-1; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); }}void upd(int x){ int lc=tr[x].lc,rc=tr[x].rc; tr[lc].c=tr[x].lazy;tr[rc].c=tr[x].lazy; tr[lc].lazy=tr[rc].lazy=tr[x].lazy; tr[x].lazy=-1;}void change(int now,int l,int r,int c){ if(tr[now].l==l && tr[now].r==r) { tr[now].c=tr[now].lazy=c; return ; } int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; if(tr[now].lazy!=-1)upd(now); if(r<=mid)change(lc,l,r,c); else if(mid+1<=l)change(rc,l,r,c); else { change(lc,l,mid,c); change(rc,mid+1,r,c); } tr[now].c=min(tr[lc].c,tr[rc].c);}int solmin(int now,int l,int r){ if(tr[now].l==l && tr[now].r==r){return tr[now].c;} int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; if(tr[now].lazy!=-1)upd(now); if(r<=mid)return solmin(lc,l,r); else if(mid+1<=l)return solmin(rc,l,r); else return min(solmin(lc,l,mid),solmin(rc,mid+1,r));}int lca(int x,int y,int op){ if(dep[x]<dep[y])swap(x,y); int tmp=x; for(int i=20;i>=0;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; if(x==y) { if(op==0)return x; for(int i=20;i>=0;i--)if(dep[fa[tmp][i]]>=dep[son[y]])tmp=fa[tmp][i]; return tmp; } for(int i=20;i>=0;i--)if(dep[x]>=bin[i] && fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; if(op==0)return fa[x][0]; return x;}void chmul(int x,int y,int c){ int tx=top[x],ty=top[y]; while(tx!=ty) { if(dep[tx]>dep[ty])swap(x,y),swap(tx,ty); change(1,ys[ty],ys[y],c); y=fa[ty][0];ty=top[y]; } if(x==y){change(1,ys[x],ys[x],c);return ;} else { if(dep[x]>dep[y])swap(x,y); change(1,ys[x],ys[y],c); }}int id;int main(){ int n,m; bin[0]=1;for(int i=1;i<=20;i++)bin[i]=bin[i-1]*2; n=read();m=read(); len=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { int x=read(),y=read(); ins(x,y);ins(y,x); } fa[1][0]=0;dep[1]=1;pre_tree_node(1); z=0;pre_tree_edge(1,1); trlen=0;bt(1,z); for(int i=1;i<=n;i++) { int x=read(); change(1,ys[i],ys[i],x); } id=read(); while(m--) { int op,x,y,c; op=read();x=read(); if(op==1)id=x; else if(op==2) { y=read();c=read(); chmul(x,y,c); } else { int cnt=lca(x,id,0); if(dep[cnt]<dep[x])printf("%d\n",solmin(1,ys[x],ys[x]+tot[x]-1)); else if(x==id)printf("%d\n",solmin(1,1,z)); else { int num=lca(x,id,1); if(ys[num]+tot[num]<=z)printf("%d\n",min(solmin(1,1,ys[num]-1),solmin(1,ys[num]+tot[num],z))); else printf("%d\n",solmin(1,1,ys[num]-1)); } } } return 0;}
- bzoj3083 遥远的国度 树链剖分+树上lca
- [bzoj3083][树链剖分][lca]遥远的国度
- 【bzoj3083】【遥远的国度】【树链剖分】
- bzoj3083: 遥远的国度
- [bzoj3083]遥远的国度
- BZOJ3083: 遥远的国度
- bzoj3083 遥远的国度
- BZOJ3083遥远的国度
- 【bzoj3083】 遥远的国度
- 【Bzoj3083】遥远的国度
- bzoj3083 遥远的国度
- 【BZOJ3083】遥远的国度,树链剖分练习
- bzoj3083 遥远的国度 树链剖分+线段树
- [BZOJ3083]遥远的国度-树链剖分-线段树
- bzoj3083遥远的国度 树链剖分+线段树
- BZOJ3083——遥远的国度
- [BZOJ3083]遥远的国度(链剖+dfs序)
- bzoj 3083: 遥远的国度 树链剖分+倍增lca
- BimServerClient使用
- Autofac官方文档(六)【注册组件之程序集扫描】
- Linux的.a、.so和.o文件
- 组合模式(java实现)
- 二叉树的直径,即二叉树的节点之间最大距离
- [bzoj3083][树链剖分][lca]遥远的国度
- mysqldiff实现MySQL数据表比较
- python基础爬虫(非框架)
- sql语句中as的用法和作用
- js和css文件自动在后缀处添加版本号(.NET)
- MySQL| MySQL关键字和保留字
- 打包布署“Windows Installer 3.1”中“PublicKey”特性的值与文件".."的值不匹配
- struts2.5 从老版本升级到2.5版本
- LeetCode基础--二叉树--ZigZag遍历