zoukankan      html  css  js  c++  java
  • [BZOJ 2631]tree

    裸LCT。。QAQ写了三遍没写对

    真是老了。。QAQ

    主要错的地方是

    init:

    size[i] = sum[i] = val[i] = mul[i] = 1;

    pushdown:

    注意判断左右儿子是否为空

    splay:

    前面有pushdown, stack..

    while(!isroot(p)){

      int x = fa[p], y = fa[x];

      if(!isroot(x))...

    }

    Access:

    while(u){

    ...

      c[u][1] = t;

      u = fa[u];
    }

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 100010
    using namespace std;
    
    typedef long long ll;
    
    const int md = 51061;
    
    int n, q;
    int c[maxn][2], fa[maxn], val[maxn], mul[maxn], add[maxn];
    int sum[maxn], top, st[maxn], size[maxn];
    bool rev[maxn];
    namespace splay{
    	inline void Mul(int& x, ll y){
    		x = x * y % md;
    	}
    	inline void Add(int& x, ll y){
    		x = (x + y) % md;
    	}
    	
    	void init(){
    		for(int i = 1; i <= n; i ++)
    		    val[i] = mul[i] = 1, add[i] = 0;
    	}
    	
    	inline void pushup(int x){
    		sum[x] = (sum[c[x][0]] + sum[c[x][1]] + val[x]) % md;
    		size[x] = size[c[x][0]] + size[c[x][1]] + 1;
    	}
    	
    	inline void pushdown(int x){
    		if(rev[x]){
    			if(c[x][0])rev[c[x][0]] ^= 1;
    			if(c[x][1])rev[c[x][1]] ^= 1;
    			swap(c[x][0], c[x][1]);
    			rev[x] = 0;
    		}
    		
    		int lc = c[x][0], rc = c[x][1];
    		if(lc != 0){
    			if(mul[x] != 1){
    				Mul(mul[lc], mul[x]);
    				Mul(add[lc], mul[x]);
    				Mul(val[lc], mul[x]);
    				Mul(sum[lc], mul[x]);
    			}
    			if(add[x] != 0){
    				Add(add[lc], add[x]);
    				Add(val[lc], add[x]);
    				Add(sum[lc], (ll)size[lc] * add[x]);
    			}
    		}
    		
    		if(rc != 0){
                if(mul[x] != 1){
    				Mul(mul[rc], mul[x]);
    				Mul(add[rc], mul[x]);
    				Mul(val[rc], mul[x]);
    				Mul(sum[rc], mul[x]);
    			}
    			if(add[x] != 0){
    				Add(add[rc], add[x]);
    				Add(val[rc], add[x]);
    				Add(sum[rc], (ll)size[rc] * add[x]);
    			}
    		}
    		mul[x] = 1, add[x] = 0;
    	}
    
    	inline bool isroot(int x){
    		return c[fa[x]][0] != x && c[fa[x]][1] != x;
    	}
    	
    	inline void rotate(int p, int x){
    		int mark = p == c[x][1], y = c[p][mark^1], z = fa[x];
    		if(c[z][0] == x) c[z][0] = p;
    		if(c[z][1] == x) c[z][1] = p;
    		if(y) fa[y] = x;
    		c[p][mark^1] = x, fa[p] = z;
    		c[x][mark] = y, fa[x] = p;
    		pushup(x);
    	}
    	
    	inline void splay(int p){
    		st[top = 1] = p;
    		for(int i = p; !isroot(i); i = fa[i])
    		    st[++ top] = fa[i];
    		while(top) pushdown(st[top --]);
    		while(!isroot(p)){
    			int x = fa[p], y = fa[x];
    			if(isroot(x))rotate(p, x);
    			else if(p == c[x][0] ^ x == c[y][0])
    				rotate(p, x), rotate(p, y);
    			else rotate(x, y), rotate(p, x);
    		}
    		pushup(p);
    	}
    	
    	inline void update(int x, int mu, int ad){
    		if(mu != 1){
    			Mul(val[x], mu);
    			Mul(mul[x], mu);
    			Mul(add[x], mu);
    			Mul(sum[x], mu);
    		}
    		
    		if(ad != 0){
    			Add(val[x], ad);
    			Add(add[x], ad);
    			Add(sum[x], (ll)size[x] * ad);
    		}
    	}
    }
    
    
    namespace LCT{
    	void Access(int u){
    		int t = 0;
    		while(u){
    			splay::splay(u);
    			c[u][1] = t;
    			t = u;
    			splay::pushup(u);
    			u = fa[u];
    		}
    	}
    	
    	void Evert(int u){
    		Access(u);
    		splay::splay(u);
    		rev[u] ^= 1;
    		splay::pushdown(u);
    	}
    	
    	void link(int u, int v){
    		Evert(u);
    		fa[u] = v;
    		//Access(u); splay::splay(u);
    	}
    	
    	void cut(int u, int v){
    		Evert(u);
    		Access(v);
    		splay::splay(v);
    		c[v][0] = fa[u] = 0;
    		splay::pushup(v);
    	}
    	
    	void update(int u, int v, int mu, int ad){
    		Evert(u), Access(v);
    		splay::splay(v);
            splay::update(v, mu, ad);
    	}
    	
    	int ask(int u, int v){
            Evert(u), Access(v);
            splay::splay(v);
            return sum[v];
    	}
    }
    
    int main(){
    	scanf("%d%d", &n, &q);
    	splay::init();
    	int u, v, u1, v1, c;
    	for(int i = 1; i < n; i ++){
    		scanf("%d%d", &u, &v);
    		LCT::link(u, v);
    	}
    	for(int i = 1; i <= q; i ++){
    		char ch = getchar();
    		for(; ch < '!'; ch = getchar());
    		if(ch == '+'){
    			scanf("%d%d%d", &u, &v, &c);
    			LCT::update(u, v, 1, c);
    		}
    		if(ch == '-'){
    			scanf("%d%d%d%d", &u, &v, &u1, &v1);
    			LCT::cut(u, v);
    			LCT::link(u1, v1);
    		}
    		if(ch == '*'){
                scanf("%d%d%d", &u, &v, &c);
    			LCT::update(u, v, c, 0);
    		}
    		if(ch == '/'){
    			scanf("%d%d", &u, &v);
    			printf("%d
    ", LCT::ask(u, v));
    		}
    	}
    	return 0;
    }
    
    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5381084.html
Copyright © 2011-2022 走看看