• [BJOI2014] 大融合


    Description

    一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。随着边的添加,动态的回答对于某些边的负载的询问。

    Solution

    回顾一下 LCT 是如何维护子树信息的

    对 lct 上每个结点,维护两个 sz 和 si,前者维护该点的信息和,后者维护该点所有虚儿子的信息

    access 操作时,将旧虚儿子从 si 中减去,将新虚儿子加入

    link f[x]=y 后,将 x 的信息计入 si[y] 中(注意用 access)

    pushup 时,按照上述公式更新一下即可

    现在回到本题,需要询问的时候,我们先将这条边断开,然后查一下两边根点的答案即可

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1000000;
    
    int n,m,val[N];
    
    namespace lct{
    	int top, q[N], ch[N][2], fa[N], rev[N];
    	int sz[N], si[N];
    	inline void pushup(int x){
    		sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+si[x]+1; //
    	}
    	inline void pushdown(int x){
    		if(!rev[x]) return;
    		rev[ch[x][0]]^=1;
    		rev[ch[x][1]]^=1;
    		rev[x]^=1;
    		swap(ch[x][0],ch[x][1]);
    	}
    	inline bool isroot(int x){
    		return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
    	}
    	inline void rotate(int p){
    		int q=fa[p], y=fa[q], x=ch[fa[p]][1]==p;
    		ch[q][x]=ch[p][x^1]; fa[ch[q][x]]=q;
    		ch[p][x^1]=q; fa[q]=p; fa[p]=y;
    		if(y) if(ch[y][0]==q) ch[y][0]=p;
    		else  if(ch[y][1]==q) ch[y][1]=p;
    		pushup(q); pushup(p);
    	}
    	inline void splay(int x){
    		q[top=1]=x;
    		for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
    		for(int i=top;i;i--) pushdown(q[i]);
    		for(;!isroot(x);rotate(x))
    			if(!isroot(fa[x]))
    				rotate((ch[fa[x]][0]==x)==(ch[fa[fa[x]]][0]==fa[x])?fa[x]:x);
    	}
    	void access(int x){
    		for(int t=0;x;t=x,x=fa[x])
    			splay(x),si[x]+=sz[ch[x][1]],si[x]-=sz[t],ch[x][1]=t,pushup(x); //
    	}
    	void makeroot(int x){
    		access(x);
    		splay(x);
    		rev[x]^=1;
    	}
    	int find(int x){
    		access(x);
    		splay(x);
    		while(ch[x][0]) x=ch[x][0];
    		return x;
    	}
    	void split(int x,int y){
    		makeroot(x);
    		access(y);
    		splay(y);
    	}
    	void cut(int x,int y){
    		split(x,y);
    		if(ch[y][0]==x)
    			ch[y][0]=0, fa[x]=0;
            pushup(y); //
    	}
    	void link(int x,int y){
    		split(x,y); // !!!
    		fa[x]=y;
    		si[y]+=sz[x]; //
    		pushup(y); //
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) lct::sz[i]=1;
    	for(int i=1;i<=m;i++){
    		char str[10]; int t1,t2;
    		scanf("%s%d%d",&str,&t1,&t2);
    		if(str[0]=='A')
    			lct::link(t1,t2);
    		if(str[0]=='Q') {
                lct::cut(t1,t2);
                lct::makeroot(t1);
                lct::makeroot(t2);
                cout<<1ll*lct::sz[t1]*lct::sz[t2]<<endl;
                lct::link(t1,t2);
    		}
    	}
    }
    
    
    
  • 相关阅读:
    ex3多类问题和NN中的前向传播
    逻辑关系下的NN应用
    NN-Neural Network
    ex2:逻辑回归及正则条件下的练习
    Overfitting&Underfitting Problems
    操作系统内存管理之虚拟内存
    C陷阱与缺陷读书笔记(三)
    操作系统常见面试题
    计算机网络常考面试题总结
    堆及堆排序
  • 原文地址:https://www.cnblogs.com/mollnn/p/13180286.html
Copyright © 2020-2023  润新知