您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: