• LUOGU P1501 [国家集训队]Tree II (lct)


    传送门

    解题思路

      (lct),比较模板的一道题,路径加和乘的维护标记与线段树(2)差不多,然后剩下就没啥了。但调了我将近一下午。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define int long long
    
    using namespace std;
    const int MAXN = 100005;
    const int MOD = 51061;
    
    inline int rd(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    	while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    
    int n,q,fa[MAXN],sum[MAXN],ch[MAXN][2],w[MAXN];
    int tag_mul[MAXN],tag_add[MAXN],siz[MAXN];
    bool tag[MAXN];
    
    inline void pushup(int x){
    	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+w[x];sum[x]%=MOD;
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    
    inline bool isroot(int x){
    	return (x!=ch[fa[x]][0] && x!=ch[fa[x]][1]);
    }
    
    inline bool check(int x){
    	return (x==ch[fa[x]][1]);
    }
    
    inline void pushdown(int x){
    	if(tag[x]){
    		if(ch[x][0]) tag[ch[x][0]]^=1,swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
    		if(ch[x][1]) tag[ch[x][1]]^=1,swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
    		tag[x]=0;
    	}
    	if(tag_mul[x]!=-1){
    		if(ch[x][0]){
    			if(tag_add[ch[x][0]]!=-1) (tag_add[ch[x][0]]*=tag_mul[x])%=MOD;
    			if(tag_mul[ch[x][0]]==-1) tag_mul[ch[x][0]]=tag_mul[x];
    			else (tag_mul[ch[x][0]]*=tag_mul[x])%=MOD;
    			w[ch[x][0]]*=tag_mul[x];w[ch[x][0]]%=MOD;
    			sum[ch[x][0]]*=tag_mul[x];sum[ch[x][0]]%=MOD;
    		}
    		if(ch[x][1]){
    			if(tag_add[ch[x][1]]!=-1) (tag_add[ch[x][1]]*=tag_mul[x])%=MOD;
    			if(tag_mul[ch[x][1]]==-1) tag_mul[ch[x][1]]=tag_mul[x];
    			else (tag_mul[ch[x][1]]*=tag_mul[x])%=MOD;
    			w[ch[x][1]]*=tag_mul[x];w[ch[x][1]]%=MOD;
    			sum[ch[x][1]]*=tag_mul[x];sum[ch[x][1]]%=MOD;
    		}
    		tag_mul[x]=-1;
    	}
    	if(tag_add[x]!=-1) {
    		if(ch[x][0]) {
    			if(tag_add[ch[x][0]]==-1) tag_add[ch[x][0]]=tag_add[x];
    			else (tag_add[ch[x][0]]+=tag_add[x])%=MOD;
    			(w[ch[x][0]]+=tag_add[x])%=MOD;
    			sum[ch[x][0]]+=siz[ch[x][0]]*tag_add[x];sum[ch[x][0]]%=MOD;
    		}
    		if(ch[x][1]){
    			if(tag_add[ch[x][1]]==-1) tag_add[ch[x][1]]=tag_add[x];
    			else (tag_add[ch[x][1]]+=tag_add[x])%=MOD;
    			(w[ch[x][1]]+=tag_add[x])%=MOD;
    			sum[ch[x][1]]+=siz[ch[x][1]]*tag_add[x];sum[ch[x][1]]%=MOD;
    		}
    		tag_add[x]=-1;
    	}
    }
    
    inline void update(int x){
    	if(!isroot(x)) update(fa[x]);pushdown(x);
    }
    
    inline void rotate(int x){
    	int y=fa[x],z=fa[y];bool chk=check(x);
    	if(!isroot(y)) ch[z][y==ch[z][1]]=x;
    	ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y;
    	fa[y]=x;ch[x][chk^1]=y;fa[x]=z;
    	pushup(y);pushup(x);
    }
    
    inline void splay(int x){
    	update(x);
    	for(;!isroot(x);rotate(x))
    		if(!isroot(fa[x])) rotate(check(fa[x])==check(x)?fa[x]:x);
    }
    
    inline void access(int x){
    	for(int y=0;x;y=x,x=fa[x])
    		splay(x),ch[x][1]=y,pushup(x);
    }
    
    inline int findroot(int x){
    	access(x);splay(x);
    	while(ch[x][0]) pushdown(x),x=ch[x][0];
    	return x;
    }
    
    inline void makeroot(int x){
    	access(x);splay(x);
    	tag[x]^=1;swap(ch[x][0],ch[x][1]);
    }
    
    inline void split(int x,int y){
    	makeroot(x);access(y);splay(y);
    }
    
    inline void link(int x,int y){
    	if(findroot(x)==findroot(y)) return;
    	makeroot(x);fa[x]=y;
    }
    
    inline void cut(int x,int y){
    	if(findroot(x)!=findroot(y)) return;
    	split(x,y);
    	if(ch[y][0]==x && !ch[x][1]) 
    		fa[x]=0,ch[y][0]=0,pushup(y);
    }
    
    inline void update_add(int x,int y,int k){
    	split(x,y);
    	if(tag_add[y]!=-1) (tag_add[y]+=k)%=MOD ;else tag_add[y]=k;
    	w[y]+=k;pushup(y);w[y]%=MOD;
    }
    
    inline void update_mul(int x,int y,int k){
    	split(x,y);
    	if(tag_add[y]!=-1) (tag_add[y]*=k)%=MOD;
    	if(tag_mul[y]!=-1) (tag_mul[y]*=k)%=MOD;else tag_mul[y]=k;
    	w[y]*=k;pushup(y);w[y]%=MOD;
    }
    
    signed main(){
    	memset(tag_mul,-1,sizeof(tag_mul));
    	memset(tag_add,-1,sizeof(tag_add));
    	int x,y,a,b;char c;n=rd(),q=rd();
    	for(int i=1;i<=n;i++) w[i]=1;
    	for(int i=1;i<n;i++){
    		x=rd(),y=rd();
    		link(x,y);
    	}
    	while(q--){
    		scanf("%c",&c);
    		if(c=='+'){
    			x=rd(),y=rd(),a=rd();
    			update_add(x,y,a);
    		}
    		else if(c=='-'){
    			x=rd(),y=rd(),a=rd(),b=rd();
    			cut(x,y);link(a,b);
    		}
    		else if(c=='*') {
    			x=rd(),y=rd(),a=rd();
    			update_mul(x,y,a);
    		}
    		else {
    			x=rd(),y=rd();
    			split(x,y);printf("%lld
    ",sum[y]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Jmeter 指令记录
    做100个用户的并发测试时是不是得要100个用户的账号呀?
    以后可能会遇到的问题记录 .send_keys 无法输入的情况
    Appscan安装问题记录 + 最后问题解决的方法 和安装步骤
    fiddler工具能干啥
    Appscan_web安全测试工具 (含修改启动浏览器的方法)
    解决需要断言多个,其中有断言错误还要继续往下断言其他的方法
    (unittest之装饰器(@classmethod)) 让多个测试用例在一个浏览器里面跑 的方法
    unittest笔记
    另外一种结尾展示方法
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9996683.html
Copyright © 2020-2023  润新知