【模板】树链剖分

题目:树链剖分

#include <bits/stdc++.h>
using namespace std;

const int Max=100005;
int n,m,s,tot,root,mod;
int l[Max],r[Max],father[Max],first[Max],num[Max],depth[Max];
int top[Max],rev[Max],seg[Max],size[Max],son[Max];
int tree[Max<<2],add[Max<<2];
struct shu{int to,next;};
shu edge[Max<<1];

inline int get_int()
{
    int x=0,f=1;
    char c;
    for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
    if(c=='-') f=-1,c=getchar();
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}
inline void print(int x)
{
    if(x>9) print(x/10);
    putchar('0'+x%10);
}

inline void build(int x,int y)
{
    edge[++s].next=first[x];
    first[x]=s;
    edge[s].to=y;
}
inline void dfs1(int p){
	size[p]=1;
	for(int i=first[p];i;i=edge[i].next){
		int v=edge[i].to;
		if(v==father[p])continue;
		father[v]=p,depth[v]=depth[p]+1,dfs1(v),size[p]+=size[v];
		if(size[v]>size[son[p]])son[p]=v;
	}
}
inline void dfs2(int p,int tp){
	top[p]=tp,seg[rev[p]=++tot]=p;
	if(!son[p])return;
	dfs2(son[p],tp);
	for(int i=first[p];i;i=edge[i].next){
		int v=edge[i].to;
		if(v!=son[p]&&v!=father[p])dfs2(v,v);
	}
}
inline void pushdown(int root,int l,int r,int mid)
{
    if(!add[root]) return;
    tree[root<<1]=(tree[root<<1]+add[root]*(mid-l+1))%mod;
    tree[root<<1|1]=(tree[root<<1|1]+add[root]*(r-mid))%mod;
    add[root<<1]=(add[root<<1]+add[root])%mod;
    add[root<<1|1]=(add[root<<1|1]+add[root])%mod;
    add[root]=0;
}
inline void update(int root){tree[root]=(tree[root<<1]+tree[root<<1|1])%mod;}
inline void buildtree(int root,int l,int r)
{
    if(l==r) {tree[root]=num[seg[l]];return;}
    int mid=(l+r)>>1;
    buildtree(root<<1,l,mid),buildtree(root<<1|1,mid+1,r);
    update(root);
}
inline void change(int root,int l,int r,int L,int R,int num)
{
    if(L<=l&&R>=r){tree[root]+=(r-l+1)*num,add[root]+=num;return;}
    int mid=(l+r)>>1;
    pushdown(root,l,r,mid);
    if(L<=mid) change(root<<1,l,mid,L,R,num);
    if(R>mid) change(root<<1|1,mid+1,r,L,R,num);
    update(root);
}
inline int Q(int root,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return tree[root];
    int mid=(l+r)>>1,sum=0;
    pushdown(root,l,r,mid);
    if(L<=mid) sum=(sum+Q(root<<1,l,mid,L,R))%mod;
    if(R>mid) sum=(sum+Q(root<<1|1,mid+1,r,L,R))%mod;
    return sum;
}

inline void modify(int x,int y,int z)
{
//    if(!y) {change(1,1,tot,l[x],r[x],z);return;}
    while(top[x]!=top[y])
    {
      if(depth[top[x]]<depth[top[y]]) swap(x,y);
      change(1,1,tot,rev[top[x]],rev[x],z);
      x=father[top[x]];
    }
    if(depth[x]>depth[y]) swap(x,y);
    change(1,1,tot,rev[x],rev[y],z);
}
inline int ask(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
      if(depth[top[x]]<depth[top[y]]) swap(x,y);
      ans=(ans+Q(1,1,tot,rev[top[x]],rev[x]))%mod;
      x=father[top[x]];
    }
    if(depth[x]>depth[y]) swap(x,y);
    ans=(ans+Q(1,1,tot,rev[x],rev[y]))%mod;
    return ans;
}

int main()
{
    n=get_int(),m=get_int(),root=get_int(),mod=get_int();
    for(int i=1;i<=n;i++) num[i]=get_int();
    for(int i=1;i<n;i++)
    {
      int x=get_int(),y=get_int();
      build(x,y),build(y,x);
    }
    dfs1(root),dfs2(root,root);
    buildtree(1,1,tot);
    for(int i=1;i<=m;i++)
    {
      int tag=get_int(),x=get_int(),y,z;
      switch(tag)
      {
      	case 1:
      		y=get_int(),z=get_int(),modify(x,y,z);
      		break;
      	case 2:
      		y=get_int(),print(ask(x,y)),putchar('\n');
      		break;
      	case 3:
      		z=get_int(),change(1,1,tot,rev[x],rev[x]+size[x]-1,z);
      		break;
      	case 4:
      		print(Q(1,1,tot,rev[x],rev[x]+size[x]-1)),putchar('\n');
      		break;
      }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <cstdio> #include <iostream> #include <vector> #define N 30003 #define INF 2147483647 using namespace std; int n,f[N][20],dep[N],siz[N],son[N],top[N],tot,pos[N],w[N]; int Max[N*4],Sum[N*4]; vector <int> to[N]; void dfs1(int x){ siz[x]=1; int sz=to[x].size(); for(int i=0;i<sz;++i){ int y=to[x][i]; if(y==f[x][0])continue; f[y][0]=x; dep[y]=dep[x]+1; dfs1(y); siz[x]+=siz[y]; if(siz[y]>siz[son[x]])son[x]=y; } } void dfs2(int x,int root){ top[x]=root; pos[x]=++tot; if(son[x])dfs2(son[x],root); int sz=to[x].size(); for(int i=0;i<sz;++i){ int y=to[x][i]; if(y==f[x][0] || y==son[x])continue; dfs2(y,y); } } void update(int k,int l,int r,int P,int V){ if(l==r){ Max[k]=Sum[k]=V; return; } int mid=(l+r)>>1; if(P<=mid)update(k*2,l,mid,P,V); else update(k*2+1,mid+1,r,P,V); Max[k]=max(Max[k*2],Max[k*2+1]); Sum[k]=Sum[k*2]+Sum[k*2+1]; } void up(int &x,int goal){ for(int i=15;i>=0;--i) if(dep[f[x][i]]>=goal)x=f[x][i]; } int lca(int x,int y){ if(dep[x]>dep[y])up(x,dep[y]); if(dep[x]<dep[y])up(y,dep[x]); if(x==y)return x; for(int i=15;i>=0;--i) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int getm(int k,int l,int r,int L,int R){ if(L<=l && r<=R)return Max[k]; int res=-INF,mid=(l+r)>>1; if(L<=mid)res=max(res,getm(k*2,l,mid,L,R)); if(R>mid)res=max(res,getm(k*2+1,mid+1,r,L,R)); return res; } int gets(int k,int l,int r,int L,int R){ if(L<=l && r<=R)return Sum[k]; int res=0,mid=(l+r)>>1; if(L<=mid)res+=gets(k*2,l,mid,L,R); if(R>mid)res+=gets(k*2+1,mid+1,r,L,R); return res; } int main(){ scanf("%d",&n); for(int i=1,a,b;i<n;++i){ scanf("%d%d",&a,&b); to[a].push_back(b); to[b].push_back(a); } dep[1]=1; dfs1(1); dfs2(1,1); for(int i=1;i<=15;++i) for(int j=1;j<=n;++j)f[j][i]=f[f[j][i-1]][i-1]; for(int i=1;i<=n;++i){ scanf("%d",&w[i]); update(1,1,n,pos[i],w[i]); } int q; scanf("%d",&q); while(q--){ char s[10]; int u,v,t; scanf("%s",s); if(s[1]=='H'){ scanf("%d%d",&u,&t); w[u]=t; update(1,1,n,pos[u],t); } if(s[1]=='M'){ scanf("%d%d",&u,&v); int ans=-INF,t=lca(u,v); for(int i=u;i;i=f[top[i]][0]) if(dep[t]<dep[top[i]]) ans=max(ans,getm(1,1,n,pos[top[i]],pos[i])); else{ ans=max(ans,getm(1,1,n,pos[t],pos[i])); break; } for(int i=v;i;i=f[top[i]][0]) if(dep[t]<dep[top[i]]) ans=max(ans,getm(1,1,n,pos[top[i]],pos[i])); else{ ans=max(ans,getm(1,1,n,pos[t],pos[i])); break; } printf("%d\n",ans); } if(s[1]=='S'){ scanf("%d%d",&u,&v); int ans=0,t=lca(u,v); for(int i=u;i;i=f[top[i]][0]) if(dep[t]<dep[top[i]]) ans+=gets(1,1,n,pos[top[i]],pos[i]); else{ ans+=gets(1,1,n,pos[t],pos[i]); break; } for(int i=v;i;i=f[top[i]][0]) if(dep[t]<dep[top[i]]) ans+=gets(1,1,n,pos[top[i]],pos[i]); else{ ans+=gets(1,1,n,pos[t],pos[i]); break; } printf("%d\n",ans-w[t]); } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值