• Luogu_ P3384 【模板】轻重链剖分


    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    struct tree{ll v,late;}t[100010<<2];
    int n,m,r,mod,val[100010],p[100010],size[100010],deep[100010],son[100010],top[100010];
    int dfn[100010],tot,id[100010],cnt[100010];
    vector<int> G[100010];
    
    void make_tree(int u,int fa){
    	size[u]=1;
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];
    		if(v==fa)continue;
    		p[v]=u;
    		deep[v]=deep[u]+1;
    		make_tree(v,u);
    		size[u]+=size[v];
    		if(size[v]>size[son[u]])son[u]=v;
    	}
    }
    
    void make_son(int u,int fa){
    	top[u]=fa;
    	dfn[u]=++tot; id[tot]=u;
    	if(son[u])make_son(son[u],fa);
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];
    		if(v!=p[u] && v!=son[u])make_son(v,v);
    	}
    	cnt[u]=tot;
    }
    
    void build_tree(int o,int l,int r){
    	if(l==r){t[o].v=val[id[l]]; return;}
    	int mid=l+r>>1;
    	build_tree(o<<1,l,mid);
    	build_tree(o<<1|1,mid+1,r);
    	t[o].v=t[o<<1].v+t[o<<1|1].v;
    }
    
    void push_down(int o,int l,int r){
    	t[o<<1].late+=t[o].late;
    	t[o<<1|1].late+=t[o].late;
    	int mid=l+r>>1;
    	t[o<<1].v+=t[o].late*(mid-l+1);
    	t[o<<1|1].v+=t[o].late*(r-mid);
    	t[o].late=0; 
    }
    
    void update(int o,int l,int r,int L,int R,int v){
    	if(L<=l && r<=R){
    		t[o].late+=v;
    		t[o].v+=(r-l+1)*v;
    		return;
    	}
    	if(t[o].late)push_down(o,l,r);
    	ll mid=l+r>>1;
    	if(mid>=L)update(o<<1,l,mid,L,R,v);
    	if(mid<R)update(o<<1|1,mid+1,r,L,R,v);
    	t[o].v=t[o<<1].v+t[o<<1|1].v;
    }
    
    ll quire(int o,int l,int r,int L,int R){
    	if(L<=l && r<=R)return t[o].v;
    	if(t[o].late)push_down(o,l,r);
    	int mid=l+r>>1;
    	ll ans=0;
    	if(L<=mid)ans+=quire(o<<1,l,mid,L,R);
    	if(mid<R)ans+=quire(o<<1|1,mid+1,r,L,R);
    	return ans;
    }
    
    void add(){
    	int x,y,z;
    	scanf("%d%d%d",&x,&y,&z);
    	while(top[x]!=top[y]){
    		if(deep[top[y]]>deep[top[x]])swap(x,y);
    		update(1,1,tot,dfn[top[x]],dfn[x],z);
    		x=p[top[x]];
    	}
    	if(deep[y]>deep[x])swap(x,y);
    	update(1,1,tot,dfn[y],dfn[x],z);
    }
    
    void get_answer(){
    	int x,y;
    	ll ans=0;
    	scanf("%d%d",&x,&y);
    	while(top[x]!=top[y]){
    		if(deep[top[y]]>deep[top[x]])swap(x,y);
    		ans+=quire(1,1,tot,dfn[top[x]],dfn[x]);
    		ans%=mod;
    		x=p[top[x]];
    	}
    	if(deep[y]>deep[x])swap(x,y);
    	ans+=quire(1,1,tot,dfn[y],dfn[x]);
    	printf("%lld
    ",ans%mod);
    }
    
    void add_son(){
    	int x,z;
    	scanf("%d%d",&x,&z);
    	update(1,1,tot,dfn[x],cnt[x],z);
    }
    
    void get_son(){
    	int x;
    	scanf("%d",&x);
    	ll ans=quire(1,1,tot,dfn[x],cnt[x]);
    	printf("%lld
    ",ans%mod);
    }
    
    int main(){
    	scanf("%d%d%d%d",&n,&m,&r,&mod);
    	for(int i=1;i<=n;i++)scanf("%d",&val[i]);
    	for(int i=1;i<n;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		G[u].push_back(v);
    		G[v].push_back(u);
    	}
    	p[r]=r;
    	make_tree(r,r);
    	make_son(r,r);
    	build_tree(1,1,tot);
    	while(m--){
    		int q;
    		scanf("%d",&q);
    		if(q==1)add();
    		if(q==2)get_answer();
    		if(q==3)add_son();
    		if(q==4)get_son();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    vue 循环Redio
    vue 子组件修改父组件变量问题
    docker安装redis
    vue 复制内容到粘贴板
    vue 组件传值
    vscode 打开多个标签页
    asp.net 文件分片上传
    css之图片下方定位遮掩层
    Python发送邮件脚本
    git添加秘钥提示Key is already in use
  • 原文地址:https://www.cnblogs.com/codetogether/p/13504285.html
Copyright © 2020-2023  润新知