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;
    }
    
    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    WinInet中的FTP操作
    CodeIgniter 用户指南 版本 1.7.2
    《Windows Mobile实例开发》电子书提供下载
    程序静默安装的参数总结
    Select a table of certain webpage
    568A
    在IIS 5.1 或IIS6 中配置PHP 的FastCGI模式
    镁天三国育将篇
    镁天三国军事篇
    windows 环境下的 protoc 安装
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5381084.html
Copyright © 2011-2022 走看看