BZOJ3083: 遥远的国度

裸的树剖   换根之后对于一个询问只需要判断当前根是否是在原树中被该节点包含就好了

人蠢代码长 没办法

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;

char c;
inline void read(long long &a)
{
	a=0;do c=getchar();while(c<'0'||c>'9');
	while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
long long Heavy_Chain_Begin[100001],Heavy_Chain_Data[100001],Heavy_Chain_Place[100001],Heavy_Chain_End[100001];
long long Heavy_Son[100001],Con_Son[100001];
bool done[1000001];
long long deep[10000001];
struct Chain
{
	Chain* next;
	long long data;
	long long other;
	Chain(){next=NULL;	}
}*Son[100001],*head[100001];
const
   long long INF=1ll<<61;
struct Segement
{
	long long l,r;
	long long data;
	long long flag;
}Segement_Tree[1000001];

void Build_Segement_Tree(long long place,long long l,long long r)
{
    Segement_Tree[place].l=l;
    Segement_Tree[place].r=r;
    Segement_Tree[place].flag=false;
    if(l==r)
       {
         Segement_Tree[place].flag=true;
       	 Segement_Tree[place].data=Heavy_Chain_Data[l];return ;
	   }
	Build_Segement_Tree(place<<1,l,(l+r)>>1);
	Build_Segement_Tree(place<<1|1,((l+r)>>1)+1,r);
	Segement_Tree[place].data=min(Segement_Tree[place<<1].data,Segement_Tree[place<<1|1].data);
}
inline void Pushdown(long long place)
{
    Segement_Tree[place<<1].flag=Segement_Tree[place<<1|1].flag=true;
    Segement_Tree[place<<1].data=Segement_Tree[place<<1|1].data=Segement_Tree[place].data;
	Segement_Tree[place].flag=false;	
} 
void Segement_Change(long long place,long long l,long long r,long long data)
{
	if(Segement_Tree[place].l>=l&&Segement_Tree[place].r<=r)
	    {Segement_Tree[place].flag=true;Segement_Tree[place].data=data;return ;		}
	if(Segement_Tree[place].flag)
	   Pushdown(place);
	if(Segement_Tree[place<<1].r>=l)
	   Segement_Change(place<<1,l,r,data);
	if(Segement_Tree[place<<1|1].l<=r)
	   Segement_Change(place<<1|1,l,r,data);
	Segement_Tree[place].data=min(Segement_Tree[place<<1].data,Segement_Tree[place<<1|1].data);
}
long long Segement_Query(long long place,long long l,long long r)
{
	long long data;
	if(l>r)
	    return INF;
	if(Segement_Tree[place].flag) 
	    return Segement_Tree[place].data;
	if(l<=Segement_Tree[place].l&&r>=Segement_Tree[place].r)
	    return Segement_Tree[place].data;
    data=INF;
	if(Segement_Tree[place<<1].r>=l)
	   data=min(data,Segement_Query(place<<1,l,r));
	if(Segement_Tree[place<<1|1].l<=r)
	   data=min(data,Segement_Query(place<<1|1,l,r));
	return data;
}
long long f[1000001];
void dfs(long long u)
{
	done[u]=true;
	Heavy_Son[u]=0;
	Con_Son[u]++;
	Chain *j,*tp;
	for(j=head[u];j;j=j->next)
	  if(!done[j->other])
	      {
	      	tp=new Chain;tp->next=Son[u];tp->other=j->other;Son[u]=tp;
	      	deep[j->other]=deep[u]+1;
	      	f[j->other]=u;
			dfs(j->other);
	      	Con_Son[u]+=Con_Son[j->other];
	      	if(Con_Son[j->other]>Con_Son[Heavy_Son[u]])Heavy_Son[u]=j->other;
		  }
}
long long Heavy_Con;
long long Data[1000001];
long long Heavy_Chain_Node[1000001];
long long root,C_root;
void dfs2(long long u,long long j)
{
	Heavy_Chain_Begin[u]=j;
	Heavy_Chain_Place[u]=++Heavy_Con;
	Heavy_Chain_Data[Heavy_Con]=Data[u];
	Heavy_Chain_Node[Heavy_Con]=u;
	if(!Heavy_Son[u])
	   goto end;
	  dfs2(Heavy_Son[u],j);
	for(Chain *tp=Son[u];tp;tp=tp->next)
	   if(tp->other!=Heavy_Son[u])
	       dfs2(tp->other,Heavy_Con+1);
	end:Heavy_Chain_End[u]=Heavy_Con;
}

inline long long Query(long long u)
{
	Chain *tp;
	long long minx,maxx;
	if(u==C_root)
	    return Segement_Query(1,1,Heavy_Con);
	if(Heavy_Chain_Place[u]<=Heavy_Chain_Place[C_root]&&Heavy_Chain_Place[C_root]<=Heavy_Chain_End[u])
	     {
	     	for(tp=Son[u];tp;tp=tp->next)
	     	   if(Heavy_Chain_Place[tp->other]<=Heavy_Chain_Place[C_root]&&Heavy_Chain_Place[C_root]<=Heavy_Chain_End[tp->other])
	     	      {
	     	         minx=Heavy_Chain_Place[tp->other];
					  maxx=Heavy_Chain_End[tp->other];	break;
				  }
			return min(Segement_Query(1,1,minx-1),Segement_Query(1,maxx+1,Heavy_Con));
		 }
	else
	   return Segement_Query(1,Heavy_Chain_Place[u],Heavy_Chain_End[u]);
}

inline long long LCA(long long a,long long b)
{
	while(Heavy_Chain_Node[Heavy_Chain_Begin[a]]!=Heavy_Chain_Node[Heavy_Chain_Begin[b]]&&a!=root&&b!=root)
	 if(deep[f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]]]>=deep[f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]]])
         a=f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]];
        else
          b=f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]];
    return deep[a]>deep[b]?b:a;
}

inline void Change(long long a,long long b)
{
    long long data;
	 read(data);
	long long ancestor=LCA(a,b); 
	while(a!=ancestor)
	{
		if(Heavy_Chain_Begin[a]==Heavy_Chain_Begin[ancestor]) 
		       {Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[a],data);break ;}
	   Segement_Change(1,Heavy_Chain_Begin[a],Heavy_Chain_Place[a],data);
	       a=f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]];
	}
	while(b!=ancestor)
	{
		if(Heavy_Chain_Begin[b]==Heavy_Chain_Begin[ancestor]) 
		       {Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[b],data);break ;}
	   Segement_Change(1,Heavy_Chain_Begin[b],Heavy_Chain_Place[b],data);
	       b=f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]];
	}
	Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[ancestor],data);
}
inline void addside(long long a,long long b)
{
	Chain *tp=new Chain;
	tp->other=b;
	tp->next=head[a];
	head[a]=tp;
}
int main()
{
	long long n,m,i,j,k,l;
     read(n),read(m);
     for(i=2;i<=n;i++)
        read(j),read(k),addside(j,k),addside(k,j);
     for(i=1;i<=n;i++)read(Data[i]);
    read(root),C_root=root;
    f[root]=root;
    dfs(root);
    dfs2(root,1);
    Build_Segement_Tree(1,1,Heavy_Con);
	for(i=1;i<=m;i++)
	   {
	     read(j);
	     if	(j==1)
	        read(C_root);
	     else if(j==2)
	         read(k),read(l),Change(k,l);
	    else read(k),printf("%lld\n",Query(k));
	  }
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值