zoukankan      html  css  js  c++  java
  • bzoj2631: tree

    话说bzoj上叫tree的题可真多...

    题目大意:路径加,路径乘,路径求和,加边删边。

    思路:动态树搞搞就行了,两个标记要注意。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll unsigned int
    #define ls c[x][0]
    #define rs c[x][1]
    const int mod=51061,maxn=100010; 
    using namespace std;
    int n,m;char op[2];
    
    struct LCT{
    	int fa[maxn],c[maxn][2],size[maxn],rev[maxn];
    	ll sum[maxn],val[maxn],mul[maxn],add[maxn];
    	bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    	int which(int x){return c[fa[x]][1]==x;}
    	void update(int x){
    //		printf("update%d %d %d
    ",x,sum[x],size[x]);
    		sum[x]=(sum[ls]+sum[rs]+val[x])%mod;
    		size[x]=(size[ls]+size[rs]+1)%mod;	
    	}
    	void cal(int x,int m,int a){
    		if (!x) return ;
    		val[x]=(val[x]*m+a)%mod;
    		sum[x]=(sum[x]*m+a*size[x])%mod;
    		add[x]=(add[x]*m+a)%mod;
    		mul[x]=(mul[x]*m)%mod;
    //		printf("%d %d %d %d
    ",x,sum[x],mul[x],add[x]);
    	}
    	void flip(int x){swap(c[x][0],c[x][1]),rev[x]^=1;}
    	void down(int x){
    		if (rev[x]) flip(c[x][0]),flip(c[x][1]),rev[x]^=1;
    		if (mul[x]!=1||add[x]) cal(ls,mul[x],add[x]),cal(rs,mul[x],add[x]),mul[x]=1,add[x]=0;
    	}
    	void relax(int x){if (!isroot(x)) relax(fa[x]);down(x);}
    	void rotate(int x){
    		int y=fa[x],z=fa[y],nx=which(x),ny=which(y);
    //		printf("%d %d %d %d
    ",x,sum[x],mul[x],add[x]);
    		fa[c[x][!nx]]=y,c[y][nx]=c[x][!nx];
    		fa[x]=z;if (!isroot(y)) c[z][ny]=x;
    		fa[y]=x,c[x][!nx]=y;update(y);
    	}
    	void splay(int x){
    		relax(x);
    		while (!isroot(x)){
    			if (isroot(fa[x])) rotate(x);
    			else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x);
    			else rotate(x),rotate(x);
    		}
    		update(x);
    	}
    	void access(int x){for (int p=0;x;x=fa[x]) splay(x),fa[c[x][1]=p]=x,update(x),p=x;}
    	void makeroot(int x){access(x),splay(x),flip(x);}
    	void link(int a,int b){makeroot(a),fa[a]=b;}
    	void cut(int a,int b){makeroot(a),access(b),splay(b),c[b][0]=fa[a]=0;}	
    	void change(int a1,int b1,int a2,int b2){cut(a1,b1),link(a2,b2);}
    	void qsum(int a,int b){makeroot(a),access(b),splay(b),printf("%d
    ",sum[b]);}
    	void modify(int a,int b,int m,int ad){makeroot(a),access(b),splay(b),cal(b,m,ad);}
    }T;
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) T.size[i]=T.val[i]=T.sum[i]=T.mul[i]=1;
    	for (int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),T.link(a,b);
    	for (int i=1,a,b,c,d;i<=m;i++){
    		scanf("%s",op);
    		if (op[0]=='+') scanf("%d%d%d",&a,&b,&c),T.modify(a,b,1,c);
    		else if (op[0]=='-') scanf("%d%d%d%d",&a,&b,&c,&d),T.change(a,b,c,d);
    		else if (op[0]=='*') scanf("%d%d%d",&a,&b,&c),T.modify(a,b,c,0);
    		else scanf("%d%d",&a,&b),T.qsum(a,b);
    	}
    	return 0;
    }


  • 相关阅读:
    CentOS安装使用.netcore极简教程(免费提供学习服务器)
    新生命团队netcore服务器免费开放计划
    线程池ThreadPool及Task调度死锁分析
    NetCore版RPC框架NewLife.ApiServer
    NewLife.Net——管道处理器解决粘包
    NewLife.Net——网络压测单机2266万tps
    NewLife.Net——构建可靠的网络服务
    NewLife.Net——开始网络编程
    搬家
    借助Redis做秒杀和限流的思考
  • 原文地址:https://www.cnblogs.com/thythy/p/5493595.html
Copyright © 2011-2022 走看看