• 洛谷.3384.[模板]树链剖分


    题目链接

    //注意树剖一条链上或一棵子树内的编号是连续的 
    //建树时用的是第二次dfs得到的序列 
    //不要频繁转longlong 
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    //#define gc() getchar()
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    const int N=1e5+5,MAXIN=1e6;
    
    int n,m,root,mod,A[N],Enum,H[N],to[N<<1],nxt[N<<1];
    int val[N],fa[N],son[N],sz[N],dep[N],top[N],cnt,id[N],sum[N<<2],tag[N<<2];
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    inline void AddEdge(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    
    void DFS1(int x)
    {
    	int mx=-1;sz[x]=1;
    	for(int i=H[x];i;i=nxt[i])
    		if(to[i]!=fa[x])
    		{
    			fa[to[i]]=x, dep[to[i]]=dep[x]+1,
    			DFS1(to[i]), sz[x]+=sz[to[i]];
    			if(mx<sz[to[i]]) son[x]=to[i],mx=sz[to[i]];
    		}
    }
    void DFS2(int x,int tp)
    {
    	id[x]=++cnt, val[cnt]=A[x], top[x]=tp;
    	if(!son[x]) return;
    	DFS2(son[x],tp);
    	for(int i=H[x];i;i=nxt[i])
    		if(to[i]!=fa[x]&&to[i]!=son[x])//if(!id[to[i]])
    			DFS2(to[i],to[i]);
    }
    inline void PushUp(int rt)
    {
    	sum[rt]=sum[rt<<1]+sum[rt<<1|1], sum[rt]>=mod?sum[rt]-=mod:0;
    }
    void PushDown(int rt,int m)
    {
    	tag[rt<<1]+=tag[rt], tag[rt<<1]>=mod?tag[rt<<1]-=mod:0;
    	tag[rt<<1|1]+=tag[rt], tag[rt<<1|1]>=mod?tag[rt<<1|1]-=mod:0;
    	sum[rt<<1]=(sum[rt<<1]+tag[rt]*(m-(m>>1)))%mod;
    	sum[rt<<1|1]=(sum[rt<<1|1]+tag[rt]*(m>>1))%mod;
    	tag[rt]=0;
    }
    void Build(int l,int r,int rt)
    {
    	if(l==r) {sum[rt]=val[l]; return;}
    	int m=l+r>>1;
    	Build(l,m,rt<<1),Build(m+1,r,rt<<1|1);
    	PushUp(rt);
    }
    void Tree_Add(int l,int r,int rt,int L,int R,int v)
    {
    	if(L<=l && r<=R)
    	{
    		sum[rt]=(sum[rt]+(r-l+1)*v)%mod,
    		tag[rt]+=v, tag[rt]>=mod?tag[rt]-=mod:0;
    		return;
    	}
    	if(tag[rt]) PushDown(rt,r-l+1);
    	int m=l+r>>1;
    	if(L<=m) Tree_Add(l,m,rt<<1,L,R,v);
    	if(m<R) Tree_Add(m+1,r,rt<<1|1,L,R,v);
    	PushUp(rt);
    }
    int Tree_Query(int l,int r,int rt,int L,int R)
    {
    	if(L<=l && r<=R) return sum[rt];
    	if(tag[rt]) PushDown(rt,r-l+1);
    	int m=l+r>>1;
    	if(L<=m)
    		if(m<R) return (Tree_Query(l,m,rt<<1,L,R)+Tree_Query(m+1,r,rt<<1|1,L,R))%mod;
    		else return Tree_Query(l,m,rt<<1,L,R);
    	else return Tree_Query(m+1,r,rt<<1|1,L,R);
    }
    void Chain_Add(int x,int y,int v)
    {
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    		Tree_Add(1,n,1,id[top[x]],id[x],v);
    		x=fa[top[x]];
    	}
    	if(id[x]>id[y]) std::swap(x,y);
    	Tree_Add(1,n,1,id[x],id[y],v);
    }
    int Chain_Query(int x,int y)
    {
    	int res=0;
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    		res+=Tree_Query(1,n,1,id[top[x]],id[x]), res>=mod?res-=mod:0;
    		x=fa[top[x]];
    	}
    	if(id[x]>id[y]) std::swap(x,y);
    	res+=Tree_Query(1,n,1,id[x],id[y]), res>=mod?res-=mod:0;
    	return res;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("3384.in","r",stdin);
    #endif
    
    	n=read(),m=read(),root=read(),mod=read();
    	for(int i=1;i<=n;++i) A[i]=read(),A[i]>=mod?A[i]%=mod:0;
    	for(int u,v,i=1;i<n;++i) u=read(),v=read(),AddEdge(u,v);
    	DFS1(root),DFS2(root,root);
    	Build(1,n,1);
    	int opt,x,y,z;
    	while(m--)
    	{
    		opt=read(),x=read();
    		if(opt==1) y=read(),z=read(),Chain_Add(x,y,z%mod);
    		else if(opt==2) y=read(),printf("%d
    ",Chain_Query(x,y));
    		else if(opt==3) y=read(),Tree_Add(1,n,1,id[x],id[x]+sz[x]-1,y%mod);
    		else printf("%d
    ",Tree_Query(1,n,1,id[x],id[x]+sz[x]-1));
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    tcpdump抓localhost 127.0.0.1的包
    fatal: write failure on 'stdout': Bad file descriptor
    rst转html
    Call to WHvSetupPartition failed: ERROR_SUCCESS (Last=0xc000000d/87) (VERR_NEM_VM_CREATE_FAILED)
    error: 'readdir_r' is deprecated [-Werror=deprecated-declarations]
    ubuntu虚拟机设置共享后无权限
    VirtualBox怎么设置从u盘启动,虚拟机从U盘启动
    File类总结
    相对路径的写法
    systeminfo总结
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8435038.html
Copyright © 2020-2023  润新知