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);
    }
    
  • 相关阅读:
    蓝桥网试题 java 基础练习 特殊的数字
    蓝桥网试题 java 基础练习 杨辉三角形
    蓝桥网试题 java 基础练习 查找整数
    蓝桥网试题 java 基础练习 数列特征
    蓝桥网试题 java 基础练习 字母图形
    蓝桥网试题 java 基础练习 01字串
    蓝桥网试题 java 基础练习 回文数
    蓝桥网试题 java 基础练习 特殊回文数
    Using text search in Web page with Sikuli
    each of which 用法
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090872.html
Copyright © 2011-2022 走看看