zoukankan      html  css  js  c++  java
  • [国家集训队]Tree II

    考虑记录如下几个量:
    v : 每个点的权值
    siz : splay中子树大小
    s : splay中子树的权值和
    lm,la : 两个标记
    然后维护操作就行。

    [国家集训队]Tree II
    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define mod 51061
    #define N 100009
    
    ll n,q,f[N],c[N][2],v[N],s[N],siz[N],lm[N],la[N],st[N];
    
    bool r[N];
    
    #define l(x) c[x][0]
    #define r(x) c[x][1]
    #define mul(x) x = (x * c) % mod
    #define add(x,y) x = (x + y) % mod
    
    inline bool nroot(int x){return l(f[x]) == x || r(f[x]) == x;}
    
    inline void up(int x){s[x] = (s[l(x)] + s[r(x)] + v[x]) % mod;siz[x] = (siz[l(x)] + siz[r(x)] + 1);}
    
    inline void pushr(int x){std::swap(l(x),r(x));r[x] ^= 1;}
    
    inline void pushm(int x,int c){mul(s[x]),mul(v[x]),mul(lm[x]),mul(la[x]);} 
    
    inline void pusha(int x,int c){add(s[x],c * siz[x]),add(v[x],c),add(la[x],c);}
    
    inline void pushdown(int x){
    	if(lm[x] != 1)pushm(l(x),lm[x]),pushm(r(x),lm[x]),lm[x] = 1;
    	if(la[x])pusha(l(x),la[x]),pusha(r(x),la[x]),la[x] = 0;
    	if(r[x]){
    	if(l(x))pushr(l(x));
    	if(r(x))pushr(r(x));
    	r[x] = 0;
    	}
    }
    
    inline void rotate(int x){
    	int y = f[x],z = f[y],k = r(y) == x,w = c[x][!k];
    	if(nroot(y))c[z][r(z) == y] = x;c[x][!k] = y;c[y][k] = w;
    	if(w)f[w] = y;f[y] = x;f[x] = z;
    	up(y),up(x);
    }
    
    inline void splay(int x){
    	int y = x,z = 0;
    	st[++z] = y;
    	while(nroot(y))st[++z] = y = f[y];
    	while(z)pushdown(st[z -- ]);
    	while(nroot(x)){
    		y = f[x],z = f[y];
    		if(nroot(y))
    		rotate((l(y) == x) ^ (l(z) == y) ? x : y);
    		rotate(x); 
    	}
    	up(x);	
    }
    
    inline void access(int x){
    	for(int y = 0;x;x = f[y = x])
    		splay(x),r(x) = y,up(x);
    }
    
    inline void makeroot(int x){access(x),splay(x),pushr(x);}
    
    inline void split(int x,int y){makeroot(x),access(y),splay(y);}
    
    inline void link(int x,int y){makeroot(x);f[x] = y;}
    
    inline void cut(int x,int y){split(x,y);f[x] = l(y) = 0;}
    
    int main(){
    	scanf("%lld%lld",&n,&q);
    	for(int i = 1;i <= n;++i)
    	v[i] = 1,siz[i] = 1,lm[i] = 1;
    	for(int i = 1;i <= n - 1;++i){
    		ll x,y;
    		scanf("%lld%lld",&x,&y);
    		link(x,y);
    	}
    	while(q -- ){
    		char a;
    		while(a != '*' && a != '/' && a != '+' && a != '-')
    		a = getchar();
    		switch(a){
    			case '+':{
    				ll x,y,k;
    				scanf("%lld%lld%lld",&x,&y,&k);
    				split(x,y),pusha(y,k); 
    				break;
    			} 
    			case '-':{
    				ll x,y;
    				scanf("%lld%lld",&x,&y);
    				cut(x,y);
    				scanf("%lld%lld",&x,&y);
    				link(x,y);
    				break;
    			}
    			case '*':{
    				ll x,y,k;
    				scanf("%lld%lld%lld",&x,&y,&k);
    				split(x,y),pushm(y,k); 		
    				break;
    			}
    			case '/':{
    				ll x,y;
    				scanf("%lld%lld",&x,&y);
    				split(x,y);
    				std::cout<<s[y]<<std::endl;
    				break;
    			}
    		} 
    		a = 'q'; 
    	}
    }
     
    

    或许写完一遍就A的感觉就是这样吧。

  • 相关阅读:
    SpringMvc执行流程
    Lock wait timeout exceeded; try restarting transaction解决方法
    MySQL删除复杂的重复数据的解决方案(一条数据项中包含多个值的情况)
    数据移植时递归运算查询部门及其下级所有部门的问题
    IDEA常用插件
    mybatis和mybatisPlus中解决实体类字段与数据库关键字冲突问题
    时间日期操作
    spring项目中使用MD5加密方式
    idea如何调出仪表盘
    scanf使用过程中的技巧与坑位
  • 原文地址:https://www.cnblogs.com/dixiao/p/14752756.html
Copyright © 2011-2022 走看看