zoukankan      html  css  js  c++  java
  • JZOJ6687. 【2020.06.04省选模拟】树没了(tree)

    Description

    在这里插入图片描述
    n,q<=2e5n,q<=2e5

    Solution

    • 切了一道维护子树size的LCT的模板题,庆祝一下(手动滑稽)
    • 首先把颜色挂在到父亲的边上(套路),那么除了每一个联通块的最顶端的点,其他点的颜色都是一样的。
    • 改点的时候就修改到它的父亲的边的连通性。
    • 仔细思考之后得出需要维护轻边到它的sz[y]Ksum sz[y]^K,以及当前点轻边连向它的sz[y]sum sz[y],还有整棵Splay子树的前者的和(即子树大小和)。
    • 操作的时候始终让最浅的点成为根,即操作完要makert它。
    • 连边删边的时候就是把两个联通块的答案减去,修改修改,再加上整个联通块的答案。
    • 还是蛮裸的。
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define maxn 200005
    #define ll long long 
    #define mo 1000000007
    using namespace std;
    
    int n,q,K,i,j,k,fa[maxn],a[maxn];
    int em,e[maxn*2],nx[maxn*2],ls[maxn];
    ll mul[maxn],ans[maxn];
    struct opr{int x,t;opr(int _x=0,int _t=0){x=_x,t=_t;}};
    vector<opr> op[maxn];
    
    void read(int &x){
    	x=0; char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar());
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    }
    
    ll ksm(ll x,ll y){
    	ll s=1;
    	for(;y;y/=2,x=x*x%mo) if (y&1) 
    		s=s*x%mo;
    	return s;
    }
    
    void insert(int x,int y){
    	em++; e[em]=y; nx[em]=ls[x]; ls[x]=em;
    	em++; e[em]=x; nx[em]=ls[y]; ls[y]=em;
    }
    
    int D[maxn];
    void BFS(){
    	int t=0,w=1; D[1]=1,fa[1]=n+1;
    	while (t<w){
    		int x=D[++t];
    		for(int i=ls[x];i;i=nx[i]) if (e[i]!=fa[x])
    			fa[e[i]]=x,D[++w]=e[i];
    	}
    }
    
    struct node{int f,tag,s[2],sz,ssz;ll q;} t[maxn];
    int nroot(int x){return t[t[x].f].s[0]==x||t[t[x].f].s[1]==x;}
    int get(int x){return t[t[x].f].s[1]==x;}
    void downtag(int x){
    	if (t[x].tag){
    		swap(t[x].s[0],t[x].s[1]);
    		if (t[x].s[0]) t[t[x].s[0]].tag^=1;
    		if (t[x].s[1]) t[t[x].s[1]].tag^=1;
    		t[x].tag=0;
    	}
    }
    
    void upd(int x){t[x].ssz=t[x].sz+t[t[x].s[0]].ssz+t[t[x].s[1]].ssz;}
    
    void rotate(int x){
    	int y=t[x].f,c=get(x);
    	t[y].s[c]=t[x].s[c^1],t[x].s[c^1]=y;
    	if (t[y].s[c]) t[t[y].s[c]].f=y;
    	if (nroot(y)) t[t[y].f].s[get(y)]=x;
    	t[x].f=t[y].f,t[y].f=x;
    	upd(y),upd(x);
    }
    
    int d[maxn];
    void remove(int x){
    	while (x) {d[++d[0]]=x;if (!nroot(x)) break;x=t[x].f;}
    	while (d[0]) downtag(d[d[0]]),d[0]--;
    }
    
    void splay(int x){
    	remove(x);
    	int y;
    	while (nroot(x)){
    		y=t[x].f;
    		if (nroot(y)) {
    			if (get(x)==get(y)) rotate(y);
    			else rotate(x);
    		}
    		rotate(x);
    	} upd(x);
    }
    
    void access(int x){
    	int y=0,z;
    	for(;x;x=t[x].f){
    		splay(x);
    		z=t[x].s[1];
    		if (z){
    			t[x].q+=mul[t[z].ssz];
    			t[x].sz+=t[z].ssz;
    		} t[x].s[1]=y;
    		if (y){
    			t[x].q-=mul[t[y].ssz];
    			t[x].sz-=t[y].ssz;
    		}
    		upd(x),y=x;
    	}
    }
    
    void makert(int x){access(x);splay(x);t[x].tag=1;}
    int findrt(int x){
    	access(x);
    	while (t[x].f) x=t[x].f;
    	downtag(x);
    	while (t[x].s[0]) x=t[x].s[0],downtag(x);
    	return x;
    }
    
    int main(){
    	freopen("ceshi.in","r",stdin);
    	freopen("ceshi.out","w",stdout);
    //	freopen("tree.in","r",stdin);
    //	freopen("tree.out","w",stdout);
    	read(n),read(q),read(K);
    	for(i=1;i<=n;i++) read(a[i]),op[a[i]].push_back(opr(i,0));
    	for(i=1;i<=n;i++) 
    		mul[i]=ksm(i,K);
    	for(i=1;i<n;i++) read(j),read(k),insert(j,k); 
    	BFS();
    	for(i=1;i<=q;i++){ 
    		ans[i]=-1;
    		char ch=getchar(); while(ch!='M'&&ch!='Q') ch=getchar();
    		if (ch=='M'){
    			read(j),read(k);
    			if (k!=a[j]){
    				op[a[j]].push_back(opr(j,0));
    				op[a[j]=k].push_back(opr(j,0));
    			}
    		} else read(k),op[k].push_back(opr(0,i));
    	}
    	for(i=1;i<=n;i++) op[a[i]].push_back(opr(i,0));
    	memset(a,0,sizeof(a));
    	for(i=1;i<=n+1;i++) t[i].sz=t[i].ssz=1;
    	for(int col=1;col<=n;col++) {
    		ll sum=0;
    		for(i=0;i<op[col].size();i++){
    			if (!op[col][i].t){
    				int x=op[col][i].x,y=fa[x],z;
    				if (!a[x]){
    					access(x),sum-=t[x].q;
    					z=findrt(y),access(z),sum-=t[z].q;
    					makert(y),splay(y);
    					t[x].f=y;
    					t[y].q+=mul[t[x].ssz];
    					t[y].sz+=t[x].ssz;
    					t[y].ssz+=t[x].ssz;
    					makert(z),access(z),sum+=t[z].q;
    				} else{
    					z=findrt(x),access(z),sum-=t[z].q;
    					makert(y),access(x),splay(x);
    					t[t[x].s[0]].f=0,t[x].s[0]=0;
    					t[x].ssz-=t[y].ssz;
    					access(x),sum+=t[x].q;
    					makert(z),access(z),sum+=t[z].q;
    				}
    				a[x]^=1;
    			} else ans[op[col][i].t]=sum;
    		}
    	}
    	for(i=1;i<=q;i++) if (ans[i]>=0) 
    		printf("%lld
    ",ans[i]%mo);
    }
    
  • 相关阅读:
    送给热爱书法的朋友们
    [原创]中秋随笔 祝大家中秋快乐
    Comsenz力邀您的加盟
    夜半冻醒有感
    Comsenz力邀您的加盟
    成熟的谷子先低头
    [转载]10个经典的web2.0配色方案网站
    无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”
    C#获取真实IP地址及分析
    使用TRY CATCH进行SQL Server异常处理
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090872.html
Copyright © 2011-2022 走看看