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

    Link

    Solution

    首先不能看错题。题目里有句话:子节点的标号为上一个 0 号操作叶子标号加 1

    它是站在全局0号操作的角度的,比如上一次在([l_0,r_0])长了一个编号为(i)的节点,这一次0操作是在([l,r]),那么长出的节点应该是(i+1)。这样意味着某个编号的节点只有它那一轮操作的([l,r])范围内的树有。也就是说每棵树终态节点编号是不一定连续的。

    而我把它理解成了这棵树中上一次0号操作的标号......(这种错误理解下每棵树终态节点编号都是连续的)。而且样例居然刚好契合这种理解!吐了

    正确理解了题意后,就会好做一些。有几个性质:

    • 因为编号为(i)的节点只在第(i-1)轮0号操作出现,而且保证询问是合法的(询问树上有的节点)。所以可以把每次操作的([l,r])扩展成([1,n])
    • 可以发现1号操作换生长节点并不会影响树的结构。也就是说每个0号操作只受时间在它之前的1号操作的影响。它一定接在它前面离它最近的在该树生效的,1号操作的生长节点下面。

    维护每棵树的形态显然是不行的。考虑从左往右遍历第1棵到第n棵树,发现两棵树之间的变化实际上就是插入、删除一些0,1号操作。所以可以维护两棵树之间的变化,即已经有第(i-1)棵树,想办法把它变成第(i)棵树。

    所以现在要考虑的问题是快速修改连边情况,可以用LCT+虚点来维护。

    先构造图:

     1.对全局的每个1操作按时间顺序建立虚点。每个虚点连向前一个虚点。第一个虚点连向1号实点,1号实点是定根。

     2.把0操作生成的实点连向时间上离它最近的那个1操作虚点(每个实点看作全局生成,不再是[l,r])。

    对于每个1操作,如果它在当前节点生效,那就把它连向对应的生长节点;如果失效,就连向前一个虚点。

    这样的话更换生长节点,修改一下虚点的连边就可以转移所有实点的连边。

    因为不能每次都遍历所有1操作看是否生效,所以可以考虑差分,让其在(l)生效,在(r+1)失效。

    还有一个问题是求两点之间路径长度不能在(split)出来了,因为这样需要(makeroot),但是维护的是有根树,直接(makeroot)会破坏原树结构。

    还是考虑差分。答案是(dis[a]+dis[b]-2 imes dis[lca(a,b)])

    (dis)是到根节点路径,可以(access,splay)来求。

    (lca)同样可以在(LCT)上求出!考虑先(access(a)),那么(a)到根的路径已经在一棵(splay)中了。这时再(access(b)),那么到达根所在的(splay)时经过的那条虚边,指向的父节点,就是(lca(a,b))

    inline int access(int x){
    		int y=0;
    		for(;x;y=x,x=fa[x])
    			splay(x),ch[x][1]=y,pushup(x);
    		return y;
    	}
    

    (access(a))之后再(access(b)),最后的那个(y)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define REP(i,a,b) for(int i=(a),ed=(b);i<=ed;++i)
    inline int read(){
    	register int x=0,f=1;register char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
    	return f?x:-x;
    }
    
    const int M=2e5+10,_=M<<1;
    int n,m,rp,vp,L[M],R[M],cnt,ans[M],ans_cnt;
    struct Squery{int type,p,x,y,id;inline bool operator<(const Squery &a)const{return p==a.p?type<a.type:p<a.p;}}q[_];
    
    namespace LCT{
    	int fa[_],ch[_][2],s[_],v[_];
    	inline void pushup(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+v[x];}
    	inline int getdir(int x){return x==ch[fa[x]][1];}
    	inline bool noroot(int x){return x==ch[fa[x]][0]||x==ch[fa[x]][1];}
    	inline void rotate(int x){
    		int f=fa[x],p=fa[f],k=getdir(x),s=ch[x][!k];
    		ch[x][!k]=f;ch[f][k]=s;if(noroot(f))ch[p][getdir(f)]=x;
    		fa[f]=x;fa[x]=p;if(s)fa[s]=f;
    		pushup(f);
    	}
    	inline void splay(int x){
    		for(int f=fa[x];noroot(x);rotate(x),f=fa[x])
    			if(noroot(f))rotate(getdir(f)==getdir(x)?f:x);
    		pushup(x);
    	}
    	inline int access(int x){
    		int y=0;
    		for(;x;y=x,x=fa[x])
    			splay(x),ch[x][1]=y,pushup(x);
    		return y;
    	}
    	inline void cut(int x){
    		access(x);splay(x);
    		ch[x][0]=fa[ch[x][0]]=0;
    		pushup(x);
    	}
    	inline void link(int x,int y){
    		access(x);splay(x);fa[x]=y;
    	}
    }using namespace LCT;
    
    int main(){
    	n=read(),m=read();vp=m;
    	L[1]=1,R[1]=n;
    	link(++vp,++rp);
    	REP(t,1,m){
    		int op=read();
    		if(!op){
    			++rp;L[rp]=read(),R[rp]=read();v[rp]=1;
    			link(rp,vp);
    		}
    		else if(op==1){
    			int l=read(),r=read(),x=read();
    			l=max(l,L[x]),r=min(r,R[x]);
    			if(l>r)continue;
    			++vp;link(vp,vp-1);
    			q[++cnt]=(Squery){0,l,vp,x,0};
    			q[++cnt]=(Squery){0,r+1,vp,vp-1,0};
    		}
    		else{
    			int x=read(),u=read(),v=read();
    			q[++cnt]=(Squery){1,x,u,v,++ans_cnt};
    		}
    	}
    	sort(q+1,q+cnt+1);
    	REP(t,1,cnt){
    		if(q[t].type){
    			int res=0,x=q[t].x,y=q[t].y,p;
    			access(x);splay(x);res+=s[x];
    			p=access(y);splay(y);res+=s[y];
    			access(p);splay(p);res-=s[p]*2;
    			ans[q[t].id]=res;
    		}
    		else{
    			cut(q[t].x);link(q[t].x,q[t].y);
    		}
    	}
    	REP(i,1,ans_cnt)printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/fruitea/p/12144834.html
Copyright © 2011-2022 走看看