3306: 树 树上倍增
2016-04-11 08:34
274 查看
傻逼题,换根分三种情况讨论。
#include<iostream> #include<cstdio> using namespace std; const int inf=1000000007; const int N=100005; int head ,next ,list ,in ,out ,deep ,pos ,val ,fa [18]; int n,Q,root,cnt,dfn; int l[N<<2],r[N<<2],mn[N<<2]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x,int y) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; } void dfs(int x) { in[x]=++dfn; pos[dfn]=x; for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=head[x];i;i=next[i]) { deep[list[i]]=deep[x]+1; fa[list[i]][0]=x; dfs(list[i]); } out[x]=dfn; } inline int lca(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for (int i=17;~i;i--) if ((1<<i)&t) x=fa[x][i]; for (int i=0;i<=17;i++) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0]; } inline void pushup(int k) { mn[k]=min(mn[k<<1],mn[k<<1|1]); } void build(int k,int x,int y) { l[k]=x; r[k]=y; if (l[k]==r[k]) { mn[k]=val[pos[l[k]]]; return; } int mid=l[k]+r[k]>>1; build(k<<1,x,mid); build(k<<1|1,mid+1,y); pushup(k); } void modify(int k,int x,int y) { if (l[k]==r[k]) { mn[k]=y; return; } int mid=l[k]+r[k]>>1; if (x<=mid) modify(k<<1,x,y); else modify(k<<1|1,x,y); pushup(k); } int query(int k,int x,int y) { if (x>y) return inf; if (l[k]==x&&r[k]==y) return mn[k]; int mid=l[k]+r[k]>>1; if (y<=mid) return query(k<<1,x,y); else if (x>mid) return query(k<<1|1,x,y); else return min(query(k<<1,x,mid),query(k<<1|1,mid+1,y)); } inline int find(int x,int f) { int y=x; for (int i=17;~i;i--) if (deep[fa[y][i]]>deep[f]) y=fa[y][i]; return y; } int main() { n=read(); Q=read(); for (int i=1;i<=n;i++) { int f=read(); val[i]=read(); if (!f) root=i; else insert(f,i); } dfs(1); build(1,1,n); while (Q--) { char opt[5]; scanf("%s",opt); int x=read(),y; switch (opt[0]) { case 'V': y=read(); modify(1,in[x],y); break; case 'E': root=x; break; case 'Q': if (root==x) printf("%d\n",mn[1]); else { int t=lca(x,root); if (t!=x) printf("%d\n",query(1,in[x],out[x])); else { int u=find(root,x); printf("%d\n",min(query(1,1,in[u]-1),query(1,out[u]+1,n))); } } break; } } return 0; }
相关文章推荐
- pie 饼子问题
- 算法_Rome to Integer
- Jquery即点既改
- 1951: [Sdoi2010]古代猪文 费马小定理+中国剩余定理+卢卡斯定理+快速幂
- 写写Django-CMS
- android studio修改module名称
- SQL中Group By的使用
- 出差(2~三)
- oracle 简述
- 3809: Gty的二逼妹子序列 莫队算法+分块
- 3720: Gty的妹子树 块状树
- php 爬虫如何爬取ajax异步加载文件
- git分支原理命令图文解析
- Unity之使用csv文件
- 3527: [Zjoi2014]力 FFT
- 如何安装体验 Ubuntu on Windows
- 2194: 快速傅立叶之二 FFT
- 2179: FFT快速傅立叶 FFT
- 【1-3】pythondb增删改查
- 推荐!国外程序员整理的机器学习资源大全