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

    Archie

    树链刨分之后很显然就成了一条一条的链

    那么用线段树维护一下就行了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,r,pp;
    struct e{
    	int to;
    	int ne;
    	int k;
    }ed[200005];
    int x,y,z,f;
    int p;
    int head[100005];
    int son[100005];
    int dep[100005];
    int sd[100005];
    int siz[100005];
    int top[100005];
    int fa[100005];
    int dfn[100005];
    int rnk[100005];
    void add(int f,int to){
    	p++;
    	ed[p].ne=head[f];
    	ed[p].to=to;
    	head[f]=p;
    }
    int tree[400001];
    int lazy[400001];
    void pushdown(int R,int l,int r){
    	if(lazy[R]){
    		lazy[R<<1]+=lazy[R];
    		lazy[R<<1|1]+=lazy[R];
    		int mid= (l+r)>>1;
    		tree[R<<1]+=lazy[R]*(mid-l+1)%pp;
    		tree[R<<1|1]+=lazy[R]*(r-mid)%pp;
    		lazy[R]=0;
    	}
    }
    void pushup(int r){
    	tree[r]=tree[r<<1]+tree[r<<1|1]; 
    }
    void add(int root,int L,int R,int l,int r,int v){
    	if(l<=L&&r>=R){
    		lazy[root]+=v;
    		tree[root]+=(R-L+1)*v%pp;
    		return ;
    	}
    	pushdown(root,L,R);
    	int mid=(L+R)>>1;
    	if(l<=mid) add(root<<1,L,mid,l,r,v);
    	if(r>mid) add(root<<1|1,mid+1,R,l,r,v);
    	pushup(root);
    }
    int query(int root,int L,int R,int l,int r){
    	if(l<=L&&r>=R){
    		return tree[root];
    	}
    	int mid=(L+R)>>1,ans=0;
    	pushdown(root,L,R);
    	ans%=pp;
    		if(l<=mid) ans+=query(root<<1,L,mid,l,r)%pp;
    		ans%=pp;
    		if(r>mid) ans+=query(root<<1|1,mid+1,R,l,r)%pp;
    	//pushup(root);
    		return ans%pp;
    }
    void dfs(int no,int f){
    	son[no]=-1;
    	siz[no]=1;
    	fa[no]=f;
    	dep[no]=dep[f]+1;
    	
    	for(int i=head[no];i;i=ed[i].ne){
    		if(ed[i].to==f) continue;
    		dfs(ed[i].to,no);
    		siz[no]+=siz[ed[i].to];
    	
    		if(son[no]==-1||siz[ed[i].to]>siz[son[no]]){
    			son[no]=ed[i].to;
    		}
    	}
    }
    int cnt;
    void dfs2(int no,int to){
    //	cout<<no<<" "<<to<<endl; 
    	cnt++;
    	dfn[no]=cnt;
    	top[no]=to;
    	rnk[cnt]=no;
    	sd[no]=dfn[no];
    	if(-1==son[no]) return ;
    	dfs2(son[no],to);
    		sd[no]=max(sd[no],sd[son[no]]);
    	for(int i=head[no];i;i=ed[i].ne){
    		if(ed[i].to==fa[no]||ed[i].to==son[no]) continue;
    		dfs2(ed[i].to,ed[i].to);
    		sd[no]=max(sd[no],sd[ed[i].to]);
    	}
    	
    }
    void work1(){
    		while(top[x]!=top[y]){
    			if(dep[top[x]]>=dep[top[y]]){ 
    			add(1,1,n,dfn[top[x]],dfn[x],z);
    				x=fa[top[x]];
    				
    			}else{
    				add(1,1,n,dfn[top[y]],dfn[y],z);
    				y=fa[top[y]];
    				
    			}
    		} 
    		if(dep[x]>dep[y]){
    			add(1,1,n,dfn[y],dfn[x],z);
    		}else{
    			add(1,1,n,dfn[x],dfn[y],z);
    		}
    } 
    void work2(){
    	int ans=0;
    		while(top[x]!=top[y]){
    			if(dep[top[x]]>=dep[top[y]]){ 
    				ans+=query(1,1,n,dfn[top[x]],dfn[x])%pp;
    				ans%=pp;
    				x=fa[top[x]];
    				
    			}else{
    				ans+=query(1,1,n,dfn[top[y]],dfn[y])%pp;
    				ans%=pp;
    				y=fa[top[y]];
    			}
    		} 
    		if(dep[x]>dep[y]){
    			ans+=query(1,1,n,dfn[y],dfn[x])%pp;
    			ans%=pp;
    		}else{
    			ans+=query(1,1,n,dfn[x],dfn[y])%pp;
    			ans%=pp;
    		}
    		cout<<ans%pp<<endl;
    } 
    int fr[1000001];
    int main(){
    	scanf("%d%d%d%d",&n,&m,&r,&pp);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&fr[i]);
    	}
    	for(int i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	} 
    	dep[r]=1;
    	dfs(r,r);
    	dfs2(r,r);
    	for(int i=1;i<=n;++i){
    		add(1,1,n,dfn[i],dfn[i],fr[i]);
    	}
    	while(m--){
    		scanf("%d",&f);
    		if(f==1){
    			scanf("%d%d%d",&x,&y,&z);
    			z%=pp;
    			work1();
    		}
    		if(f==2){
    			scanf("%d%d",&x,&y);
    			work2(); 
    		}
    		if(f==3) {
    			scanf("%d%d",&x,&z);
    			z%=pp;
    			add(1,1,n,dfn[x],sd[x],z);
    		}
    		if(f==4) {
    			scanf("%d",&x);
    			cout<<query(1,1,n,dfn[x],sd[x])%pp<<endl;;
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/For-Miku/p/15041487.html
Copyright © 2011-2022 走看看