首页 > 代码库 > bzoj4285: 使者

bzoj4285: 使者

搞出dfs序,转化为查询矩形点数,树套树搞定。

#include<cstdio>#include<cstdlib>#define N 100005#define IF else ifstruct edge{	edge* s;	int v;}z[N*2],*next=z,*h[N];int n,m,q;void add(int u,int v){	h[u]=&(*next++	=(edge){h[u],v});	h[v]=&(*next++	=(edge){h[v],u});}typedef int ds[N];ds d,p,r,l,son,y;void dfs1(int u){	r[u]=1;	d[u]=d[p[u]]+1;	int s=0;	for(edge* i=h[u];i;i=i->s)		if(i->v!=p[u]){			p[i->v]=u;			dfs1(i->v);			r[u]+=r[i->v];			if(s<r[i->v])				s=r[son[u]=i->v];		}}void dfs2(int u){	static int j;	l[u]=++j;	if(r[u]!=1){		y[son[u]]=y[u];		dfs2(son[u]);	}	for(edge* i=h[u];i;i=i->s)		if(i->v!=p[u]		&&i->v!=son[u])			dfs2(y[i->v]=i->v);}int lca(int s,int t){	while(y[s]^y[t])		d[y[s]]<d[y[t]]?		(s^=t,t^=s,s^=t)		:0,s=p[y[s]];	return d[s]<d[t]?s:t;}struct node{	int v,s,a,q;	node *l,*r;	void up(){		s=l->s+r->s+a;	}}*f[N],e[N*40];node* back=e+1;node* create(int v){	return &(*back++	=(node){v,	1,1,rand(),e,e});}void lturn(node*& s){	node* a=s->r;	s->r=a->l;	s->up(),a->l=s;	a->up(),s=a;}void rturn(node*& s){	node* a=s->l;	s->l=a->r;	s->up(),a->r=s;	a->up(),s=a;}void ins(int v,node*& s){	if(!s->s)		s=create(v);	IF(v==s->v)		++s->a,s->up();	IF(v<s->v){		ins(v,s->l);		if(s->l->q>s->q)			rturn(s);		else s->up();	}else{		ins(v,s->r);		if(s->r->q>s->q)			lturn(s);		else s->up();	}}void del(int v,node*& s){	if(v<s->v)		del(v,s->l),s->up();	IF(s->v<v)		del(v,s->r),s->up();	IF(s->a>1)		--s->a,s->up();	IF(s->l==e)s=s->r;	IF(s->r==e)s=s->l;	IF(s->l->q>s->r->q)		rturn(s),		del(v,s->r),s->up();	else lturn(s),		del(v,s->l),s->up();}int query(int v,node* s){	int k=0;	while(s->s)		if(v<s->v)s=s->l;		else			k+=s->l->s			+s->a,s=s->r;	return k;}int query(int i,int j){	for(int k=0;;i^=i&-i){		if(!i)return k;		k+=query(j,f[i]);	}}void ins1(int i,int j){	for(;i<=n;i+=i&-i)		ins(j,f[i]);}void ins2(int s,int t){	if(l[s]<l[t])		s^=t,t^=s,s^=t;	ins1(l[t],l[s]);}void del1(int i,int j){	for(;i<=n;i+=i&-i)		del(j,f[i]);}void del2(int s,int t){	if(l[s]<l[t])		s^=t,t^=s,s^=t;	del1(l[t],l[s]);}int query(int i,int j,int s,int t){	return query(j,t)	-query(j,s-1)	-query(i-1,t)	+query(i-1,s-1);}int find(int s,int t){	static int j;	for(;y[s]^y[t];s=p[j])		j=y[s];	return s^t?son[t]:j;}int qtree(int s,int t){	if(d[s]<d[t])		s^=t,t^=s,s^=t;	static int i,j,k;	i=l[s],j=l[s]+r[s]-1;	if(lca(s,t)!=t)		return l[s]<l[t]		?query(i,j,		l[t],l[t]+r[t]-1)		:query(l[t],		l[t]+r[t]-1,i,j);	k=find(s,t);	return(l[k]+r[k]>n?0	:query(i,j,l[k]+r[k],n))	+query(1,l[k]-1,i,j);}int main(){	struct{		operator int(){			int x;			scanf("%d",&x);			return x;		}	}it;	n=it;	for(int i=0;i<=n;++i)		f[i]=e;	for(int i=1;i!=n;++i)		add(it,it);	dfs1(1),dfs2(y[1]=1);	for(m=it;m;--m)		ins2(it,it);	for(q=it;q;--q){		int k=it,s=it,t=it;		if(k==3)			printf("%d\n",			qtree(s,t));		if(k==1)ins2(s,t);		if(k==2)del2(s,t);	}}

  

bzoj4285: 使者