zoukankan      html  css  js  c++  java
  • [ZJOI2016]大森林

    题目

    洛谷
    BZOJ
    离线神仙题

    做法

    ((0))区间生长((1))区间换点((2))单点查询

    考虑仅一次区间换点((l,r,x)),区间生长:
    就相当于换点后的生长的点在l时接在(x)上,到(r+1)时再接回去

    有多次换点也同理,对每个换点新增一个虚点,建立一条虚链,每次生长则(link)到最近的前一个虚点

    然后离线升序排树处理

    My complete code

    #include<bits/stdc++.h>
    using namespace std;
    typedef int LL;
    inline LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){ if(c=='-')c=-1; c=getchar(); }
    	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    	return x*f;
    }
    const LL maxn=1e6;
    LL n,m,nod,tot,now,num;
    LL son[maxn][2],fa[maxn],size[maxn],w[maxn],r[maxn],ans[maxn],sta[maxn],pos[maxn],gl[maxn],gr[maxn];
    inline bool Nroot(LL x){ return (son[fa[x]][0]==x || son[fa[x]][1]==x); }
    inline void Update(LL x){ size[x]=size[son[x][0]]+size[son[x][1]]+w[x]; }
    inline void Rotate(LL x){
    	LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
    	if(Nroot(y)) son[z][son[z][1]==y]=x; fa[x]=z;
    	son[y][lz]=son[x][lz^1];
    	if(son[y][lz]) fa[son[y][lz]]=y;
    	son[x][lz^1]=y, fa[y]=x;
    	Update(y), Update(x);
    }
    inline void Splay(LL x){
    	while(Nroot(x)){
    		LL y=fa[x];
    		if(Nroot(y)){
    			LL z(fa[y]);
    			((son[y][1]==x)^(son[z][1]==y))?Rotate(y):Rotate(x);
    		}Rotate(x);
    	}
    }
    inline LL Access(LL x){
    	LL lst(x);
    	for(LL y=0;x;y=x,x=fa[x])
    	    lst=x, Splay(x), son[x][1]=y, Update(x);
    	return lst;
    }
    inline void Link(LL x,LL y){
    	Splay(x), fa[x]=y;
    }
    inline void Cut(LL x){
    	Access(x), Splay(x);
    	son[x][0]=fa[son[x][0]]=0;
    	Update(x);
    }
    inline LL Lca(LL x,LL y){
    	Access(x); return Access(y);
    }
    
    struct node{
    	LL tree,id,x,y;
    }a[maxn];
    inline bool cmp(node x,node y){
    	if(!(x.tree ^ y.tree)) return x.id<y.id;
    	return x.tree<y.tree;
    }
    int main(){
    	n=Read(), m=Read();
    	nod=w[1]=size[1]=pos[1]=gl[1]=1,gr[1]=n;
    	Link(now=tot=2,1);
    	for(LL i=1;i<=m;++i){
    		LL opt(Read()),l(Read()),r(Read());
    		if(opt==0){
    			Link(pos[++nod]=++tot,now);
    			w[tot]=size[tot]=1;
    			gl[nod]=l, gr[nod]=r;
    		}else if(opt==1){
    			LL x; cin>>x;
    			l=max(l,gl[x]), r=min(r,gr[x]);
    			if(l>r) continue;
    			Link(++tot,now);
    			a[++num]=(node){l,i-m,tot,pos[x]};
    			a[++num]=(node){r+1,i-m,tot,now};
    			now=tot;
    		}else{
    			LL x(l),u(r),v(Read());
    		    a[++num]=(node){x,++ans[0],pos[u],pos[v]};
    		}
    	}
    	sort(a+1,a+1+num,cmp);
    	for(LL i=1;i<=num;++i){
    		if(a[i].id>0){
    			LL x(a[i].x),y(a[i].y),lca(Lca(x,y));
    			Access(x), Splay(x); ans[a[i].id]+=size[x];
    			Access(y), Splay(y); ans[a[i].id]+=size[y];
    			Access(lca), Splay(lca); ans[a[i].id]-=2*size[lca];
    		}else
    			Cut(a[i].x),Link(a[i].x,a[i].y);
    	}
    	for(LL i=1;i<=ans[0];++i) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    百鸡问题-小记
    vs2005下opengl(glut)的配置记录
    GSL+DevC++使用
    VS2005下使用GSL-1.15小结
    GSL--GNU Scientific Library 小记
    Window下设置Octave
    0欧姆电阻和磁珠的作用
    关于接地:数字地、模拟地、信号地、交流地、直流地、屏蔽地、浮地,特别经典哦
    altium designer设置不会产生.pcbpreview、.schpreview等的垃圾文件
    【剑指Offer面试题】 九度OJ1516:调整数组顺序使奇数位于偶数前面
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10413059.html
Copyright © 2011-2022 走看看