zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Good Bye 2014 B. New Year Permutation(floyd )
    hdu 5147 Sequence II (树状数组 求逆序数)
    POJ 1696 Space Ant (极角排序)
    POJ 2398 Toy Storage (叉积判断点和线段的关系)
    hdu 2897 邂逅明下 (简单巴什博弈)
    poj 1410 Intersection (判断线段与矩形相交 判线段相交)
    HDU 3400 Line belt (三分嵌套)
    Codeforces Round #279 (Div. 2) C. Hacking Cypher (大数取余)
    Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)
    hdu 1576 A/B (求逆元)
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9996683.html
Copyright © 2011-2022 走看看