【bzoj3306】 树 dfs序+线段树
来源:互联网 发布:手机淘宝封面模版 编辑:程序博客网 时间:2024/05/18 01:23
并不是太难,只要处理换根操作就好了,因为这棵树的形态是不变的。那么按照点1为根时的dfs序,若当前根在x点的子树外,则答案还是x的子树,若当前根是x,那么答案是整棵树,若当前的根在x的子树内,则答案就是抠掉根所在的那一枝后的答案(画个图就明白了)。
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#define maxn 100010#define inf 1000000000using namespace std;struct yts{int data;int l,r;}a[4*maxn];int e[maxn],next[2*maxn],head[maxn],to[2*maxn],g[maxn],w[maxn],in[maxn],out[maxn];int fa[maxn][20],dep[maxn];int n,m,root,num,T,tot;void addedge(int x,int y){num++;to[num]=y;next[num]=head[x];head[x]=num;}void dfs(int x){e[++tot]=x;in[x]=tot;for (int p=head[x];p;p=next[p]) if (to[p]!=g[x]) dep[to[p]]=dep[x]+1,dfs(to[p]);out[x]=tot;}void build(int i,int l,int r){a[i].l=l;a[i].r=r;if (l==r) {a[i].data=w[e[l]];return;}int mid=(l+r)/2;build(i*2,l,mid);build(i*2+1,mid+1,r);a[i].data=min(a[i*2].data,a[i*2+1].data);}void modify(int i,int x,int d){if (a[i].l==a[i].r) {a[i].data=d;return;}int mid=(a[i].l+a[i].r)/2;if (x<=mid) modify(i*2,x,d);if (mid<x) modify(i*2+1,x,d);a[i].data=min(a[i*2].data,a[i*2+1].data);}int query(int i,int l,int r){if (l>r) return inf;if (l<=a[i].l && a[i].r<=r) return a[i].data;int mid=(a[i].l+a[i].r)/2,ans=inf;if (l<=mid) ans=min(ans,query(i*2,l,r));if (mid<r) ans=min(ans,query(i*2+1,l,r));return ans;}int go_up(int x,int d){for (int i=19;i>=0;i--) if (d&(1<<i)) x=fa[x][i];return x;}int main(){scanf("%d%d",&n,&T);for (int i=1;i<=4*n;i++) a[i].data=inf;for (int i=1;i<=n;i++) scanf("%d%d",&g[i],&w[i]);for (int i=1;i<=n;i++) if (g[i]) addedge(g[i],i); else root=i;dep[1]=0;dfs(1);for (int i=1;i<=n;i++) fa[i][0]=g[i];for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1]; else fa[i][j]=0;build(1,1,n);while (T--){char op[5];int x,y;scanf("%s%d",op,&x);if (op[0]=='V'){scanf("%d",&y);modify(1,in[x],y);}if (op[0]=='E') root=x;if (op[0]=='Q'){if (root==x) printf("%d\n",query(1,1,n));else if (in[x]<=in[root] && out[root]<=out[x]) {int y=go_up(root,dep[root]-dep[x]-1);printf("%d\n",min(query(1,1,in[y]-1),query(1,out[y]+1,n)));}else printf("%d\n",query(1,in[x],out[x]));}}return 0;}
0 0
- 【bzoj3306】 树 dfs序+线段树
- 【bzoj3306】【树】【dfs序+线段树】
- [bzoj3306]树 dfs序+线段树
- [BZOJ3306]树(dfs序)
- 【bzoj3306】树
- bzoj3306 树
- BZOJ3306树
- bzoj3306: 树
- bzoj3306 树
- BZOJ3306: 树
- bzoj3306: 树
- 【bzoj3306】树
- 【bzoj3306】树
- (线段树+dfs序)
- DFS序+线段树
- HDU5692 线段树+dfs序
- 【线段树+dfs序】J
- 线段树2.0+dfs序
- Ubuntu 网卡桥接及桥接后网络不通的解决方法
- [NOIP2010]乌龟棋(DP)
- 图片 旋转,缩放,移动
- 【Bash百宝箱】vi常用快捷命令大全
- java 之 面向对象的陷阱
- 【bzoj3306】 树 dfs序+线段树
- IOS中CALayer的使用
- 栈 Deque
- mysql中文乱码解决方案
- 几何画板中的轨迹法怎样构造双曲线
- win10 亮度不能调节的解决办法(亲测办法,安装两台win10两台都是这样解决)
- UI星辰:UI代码创建视图和Label设置
- 关于STRUCT命名的问题
- POJ 1182 食物链