遥远的国度 bzoj3083

分析:

这个题一看就是裸的树剖...

唯一值得考虑的就是它的根一直在变化,我们可以这样想,如果假根在这个点的子树外,那么直接将这个点的子树作为答案区间,如果在子树内,则相对复杂,我们假设son为root所在的节点x的儿子的子树内的儿子编号,那么答案就是min(1到idx[son]-1,idx[son]+siz[son]到n),而如何求son...(这题数据水,暴力可过)详情请见代码,是树剖的一种应用。

本人wa了一天(没有考虑到ro0t==x的请况),在这种情况下,直接查1-n的最小值就行

附上代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;
#define N 300005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct node
{
int to,next;
}e[N<<1];
int head[N],cnt,dep[N],fa[N],rot,anc[N],n,Q,siz[N],son[N],idx[N],tims,p[N];
long long minn[N<<2],cov[N<<2],a[N];
void add(int x,int y)
{
e[cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt++;
return ;
}
void dfs1(int x,int from)
{
fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=from)
{
dfs1(to1,x);
siz[x]+=siz[to1];
if(siz[son[x]]<siz[to1])son[x]=to1;
}
}
}
void dfs2(int x,int top)
{
anc[x]=top;idx[x]=++tims;p[tims]=x;
if(son[x])dfs2(son[x],top);
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1);
}
}
void PushUp(int rt)
{
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void PushDown(int rt)
{
if(cov[rt])
{
cov[rt<<1]=cov[rt];
minn[rt<<1]=cov[rt];
cov[rt<<1|1]=cov[rt];
minn[rt<<1|1]=cov[rt];
cov[rt]=0;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
minn[rt]=a[p[l]];
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void Update(int L,int R,long long c,int l,int r,int rt)
{
if(L<=l&&r<=R){cov[rt]=minn[rt]=c;return ;}
PushDown(rt);int m=(l+r)>>1;
if(m>=L)Update(L,R,c,lson);
if(m<R)Update(L,R,c,rson);
PushUp(rt);
}
long long query(int L,int R,int l,int r,int rt)
{
if(L>R)return 1ll<<32;
if(L<=l&&r<=R)return minn[rt];
PushDown(rt);int m=(l+r)>>1;long long ret=1ll<<32;
if(m>=L)ret=min(query(L,R,lson),ret);
if(m<R)ret=min(query(L,R,rson),ret);
PushUp(rt);
return ret;
}
void get_lca_Update(int x,int y,long long c)
{
while(anc[x]!=anc[y])
{
if(dep[anc[x]]<dep[anc[y]])swap(x,y);
Update(idx[anc[x]],idx[x],c,1,n,1);
x=fa[anc[x]];
}
if(dep[x]>dep[y])swap(x,y);
Update(idx[x],idx[y],c,1,n,1);
}
int get_lca(int x,int y)
{
if(anc[x]==anc[y])return son[y];
while(anc[fa[anc[x]]]!=anc[y])
{
x=fa[anc[x]];
}
if(fa[anc[x]]!=y)return son[y];
return anc[x];
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&Q);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
dfs1(1,0);
dfs2(1,1);
build(1,n,1);
scanf("%d",&rot);
while(Q--)
{
int op,x,y;long long z;
scanf("%d%d",&op,&x);
//for(int i=1;i<=n;i++)printf("%d ",query(idx[i],idx[i],1,n,1));
// puts("");
if(op==3)
{
if(rot==x)printf("%lld\n",query(1,n,1,n,1));
else if(idx[rot]>=idx[x]+siz[x]||idx[rot]<=idx[x])
printf("%lld\n",query(idx[x],idx[x]+siz[x]-1,1,n,1));
else
{
int t=get_lca(rot,x);
printf("%lld\n",min(query(1,idx[t]-1,1,n,1),query(idx[t]+siz[t]-1,n,1,n,1)));
}
}else if(op==2)
{
scanf("%d%lld",&y,&z);
// int a=query(idx[x],idx[x],1,n,1),b=query(idx[y],idx[y],1,n,1);
get_lca_Update(x,y,z);
// Update(idx[x],idx[x],a,1,n,1),Update(idx[y],idx[y],b,1,n,1);
}else rot=x;
}
return 0;
}

  

上一篇:DIV周边添加投影及背景固定


下一篇:leetcode每日刷题计划-简单篇day12