码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4285: 使者

时间:2016-09-12 14:24:05      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

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

#include<cstdio>
#include<cstdlib>
#define N 100005
#define IF else if
struct 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: 使者

标签:

原文地址:http://www.cnblogs.com/f321dd/p/5864502.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!