• BZOJ4285: 使者


    搞出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;
    	for(;;s=s->r){
    		while(s->s&&v<s->v)
    			s=s->l;
    		if(!s->s)
    			break;
    		k+=s->l->s+s->a;
    	}
    	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
    ",qtree(s,t));
    		if(k==1)
    			ins2(s,t);
    		if(k==2)
    			del2(s,t);
    	}
    }
    
  • 相关阅读:
    创建SSIS包—ETL中典型的数据清洗
    SSIS中的容器和数据流—数据转换(Transformations)
    创建SSIS包—循环和动态package
    SSIS中的容器和数据流—数据转换(Transformations)续
    创建SSIS包—建立端到端的package
    SQL点滴9—SQL Server中的事务处理以及SSIS中的内建事务
    SSIS中的容器和数据流—调试工具数据视图
    SQL点滴11—重置win7登录密码影响SQL登录
    SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
    SSIS中的容器和数据流—举例说明数据转换任务
  • 原文地址:https://www.cnblogs.com/f321dd/p/5864502.html
Copyright © 2020-2023  润新知