zoukankan      html  css  js  c++  java
  • P3384 【模板】树链剖分

     

     

    题目地址


    易错点:

    • 比较top深度而不是自己(炫富就看家庭背景).


    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN=2e5,MAXM=2e5;
    struct Edge{
    	int from,to,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v){
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    struct Node{
    	int ls,rs;
    	long long lazy,sum;
    }tr[MAXN*4];
    int nodeCnt=0;
    void insert(int &now,int l,int r,int ll,int rr,long long val){
    	if(!now)now=++nodeCnt;
    	int b=min(r,rr)-max(l,ll)+1;
    	tr[now].sum+=val*b;
    	if(l>=ll&&r<=rr){
    		tr[now].lazy+=val;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(ll<=mid)insert(tr[now].ls,l,mid,ll,rr,val);
    	if(rr>mid)insert(tr[now].rs,mid+1,r,ll,rr,val);
    }
    long long query(int now,int l,int r,int ll,int rr){//求和 
    	if(l>=ll&&r<=rr){
    		return tr[now].sum;
    	}
    	int mid=(l+r)>>1;
    	if(tr[now].lazy){
    		if(!tr[now].ls)tr[now].ls=++nodeCnt;
    		tr[tr[now].ls].lazy+=tr[now].lazy;
    		tr[tr[now].ls].sum+=tr[now].lazy*(mid-l+1);
    		if(!tr[now].rs)tr[now].rs=++nodeCnt;
    		tr[tr[now].rs].lazy+=tr[now].lazy;
    		tr[tr[now].rs].sum+=tr[now].lazy*(r-mid);
    		tr[now].lazy=0;
    	}
    	long long ans=0;
    	if(ll<=mid)ans+=query(tr[now].ls,l,mid,ll,rr);
    	if(rr>mid)ans+=query(tr[now].rs,mid+1,r,ll,rr);
    	return ans;
    }
    int root=0;
    int siz[MAXN],son[MAXN];
    int fa[MAXN];
    int dep[MAXN];
    void dfs1(int x){
    	siz[x]=1;
    	dep[x]=dep[fa[x]]+1;
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(!siz[nowV]){
    			fa[nowV]=x;
    			dfs1(nowV);
    			siz[x]+=siz[nowV];
    			if(siz[nowV]>siz[son[x]]){
    				son[x]=nowV;
    			}
    		}
    	}
    }
    int num[MAXN],numCnt=0;
    int pointValue[MAXN];//每个点的原始权值 
    int top[MAXN];
    void dfs2(int x){
    	num[x]=++numCnt;
    	insert(root,1,MAXN,num[x],num[x],pointValue[x]);
    	if(x==son[fa[x]])top[x]=top[fa[x]];
    	else top[x]=x;
    	if(son[x])dfs2(son[x]);
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(!num[nowV])
    			dfs2(nowV);
    	}
    }
    void modify(int x,int y,int val){//x到y的所有结点加值 
    	while(top[x]!=top[y]){
    		if(dep[top[x]]>dep[top[y]])swap(x,y);
    		insert(root,1,MAXN,num[top[y]],num[y],val);
    		y=fa[top[y]];
    	}
    	if(num[x]>num[y])swap(x,y);
    	insert(root,1,MAXN,num[x],num[y],val);
    }
    int p;//取模 
    long long sum(int x,int y){//求x到y的所有结点值之和 
    	long long ans=0;
    	while(top[x]!=top[y]){
    		if(dep[top[x]]>dep[top[y]])swap(x,y);
    		ans+=query(root,1,MAXN,num[top[y]],num[y]);
    		ans%=p;
    		y=fa[top[y]];
    	}
    	ans+=query(root,1,MAXN,min(num[x],num[y]),max(num[x],num[y]));
    	ans%=p;
    	return ans;
    }
    int main(){
    	int n,m,r;
    	cin>>n>>m>>r>>p;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&pointValue[i]);
    	}
    	for(int i=1;i<=n-1;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		addEdge(x,y);
    		addEdge(y,x);
    	}
    	dfs1(r);
    	dfs2(r);
    	for(int i=1;i<=m;i++){
    		int opt;
    		cin>>opt;
    		if(opt==1){
    			int x,y,z;
    			scanf("%d%d%d",&x,&y,&z);
    			modify(x,y,z);
    		}else if(opt==2){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			printf("%lld
    ",sum(x,y)%p);
    		}else if(opt==3){
    			int x,z;
    			scanf("%d%d",&x,&z);
    			insert(root,1,MAXN,num[x],num[x]+siz[x]-1,z);
    		}else if(opt==4){
    			int x;
    			scanf("%d",&x);
    			printf("%lld
    ",query(root,1,MAXN,num[x],num[x]+siz[x]-1)%p);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    2011 ACM-ICPC 成都赛区解题报告(转)
    Subarray Sorting (线段树)
    sample
    gamma correction / /alpha blend
    mipmap
    antialiasing
    汇编指令
    zfighting 的问题
    勉励自己
    Ambient Occulution
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11734447.html
Copyright © 2011-2022 走看看