• 洛谷 3833 SHOI 2012 魔法树


    【题解】

      树链剖分模板题。。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define N 500010
    #define rg register
    #define ls (u<<1)
    #define rs (u<<1|1)
    #define mid ((a[u].l+a[u].r)>>1)
    #define len(x) (a[x].r-a[x].l+1)
    using namespace std;
    int n,m,rt,num,x,y,z,fa[N],dfn[N],dep[N],size[N],heavy[N],top[N];
    vector<int>son[N];
    struct tree{
    	int l,r;
    	long long sum,del;
    }a[N];
    inline int read(){
    	int k=0,f=1; char c=getchar();
    	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    	return k*f;
    }
    inline void pushup(int u){
    	a[u].sum=a[ls].sum+a[rs].sum;
    }
    inline void pushdown(int u){
    	if(!a[u].del) return; long long d=a[u].del; a[u].del=0;
    	a[ls].del+=d; a[ls].sum+=d*len(ls);
    	a[rs].del+=d; a[rs].sum+=d*len(rs);
    }
    void build(int u,int l,int r){
    	a[u].l=l; a[u].r=r; a[u].sum=a[u].del=0;
    	if(l<r) build(ls,l,mid),build(rs,mid+1,r);
    }
    void update(int u,int l,int r,long long d){
    	if(l<=a[u].l&&a[u].r<=r){
    		a[u].del+=d; a[u].sum+=d*len(u); return;
    	}
    	pushdown(u);
    	if(l<=mid) update(ls,l,r,d);
    	if(r>mid) update(rs,l,r,d);
    	pushup(u);
    }
    long long query(int u,int l,int r){
    	if(l<=a[u].l&&a[u].r<=r) return a[u].sum;
    	pushdown(u); long long ret=0;
    	if(l<=mid) ret+=query(ls,l,r);
    	if(r>mid) ret+=query(rs,l,r);
    	return ret;
    }
    void dfs1(int x){
    	size[x]=1; dep[x]=dep[fa[x]]+1;
    	for(rg int i=0;i<son[x].size();i++){
    		dfs1(son[x][i]);
    		size[x]+=size[son[x][i]];
    		if(size[son[x][i]]>size[heavy[x]]) heavy[x]=son[x][i];
    	}
    }
    void dfs2(int x,int tp){
    	top[x]=tp; dfn[x]=++num;
    	if(heavy[x]) dfs2(heavy[x],tp);
    	for(rg int i=0;i<son[x].size();i++)
    		if(son[x][i]!=heavy[x]) dfs2(son[x][i],son[x][i]);
    }
    int main(){
    	n=read(); 
    	for(rg int i=1;i<n;i++){
    		int x=read(),y=read();
    		fa[y]=x; son[x].push_back(y);
    		if(x==0) rt=x;
    	}
    	dfs1(rt); dfs2(rt,rt); 
    //	for(rg int i=0;i<=n;i++) printf("%d ",size[i]); puts("");
    //	for(rg int i=0;i<=n;i++) printf("%d ",dfn[i]); puts("");
    	build(1,1,n);
    	m=read();
    	while(m--){
    		char c=getchar();
    		while(c!='A'&&c!='Q')c=getchar();
    		if(c=='A'){
    			x=read(),y=read(),z=read();
    			while(top[x]!=top[y]){
    				if(dep[top[x]]<dep[top[y]]) swap(x,y);
    				update(1,dfn[top[x]],dfn[x],z);
    				x=fa[top[x]];
    			}
    			if(dep[x]>dep[y]) swap(x,y);
    			update(1,dfn[x],dfn[y],z);
    		}
    		else x=read(),printf("%lld
    ",query(1,dfn[x],dfn[x]+size[x]-1));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    python学习总结
    内存池设计与实现
    RFC太网接口类型定义
    linux下查看网卡速率
    linux 下的clock_gettime() 获取时间函数
    添加linux系统调用的两种方式
    内核态与用户态通信 之 sockopt
    linux进程间通信方式
    linux进程间通信同步-共享内存
    Linux忘记密码常用的几种解决方法
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8612034.html
Copyright © 2020-2023  润新知