树链剖分 模板

匿名 (未验证) 提交于 2019-12-02 23:47:01

修改与查询整个子树

修改与查询路径

#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v)  memset(A,v,sizeof A) #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 typedef pair<int,int>pii; ////////////////////////////////// const int N=2e6+10; const int M=1e6;  int t[N<<2],col[N<<2],w[N],n,mod,m,root,node[N];  void up(int pos) {     t[pos]=t[pos<<1]+t[pos<<1|1];t[pos]%=mod; } void down(int m,int pos) {     if(col[pos])     {         col[pos<<1]+=col[pos];         col[pos<<1|1]+=col[pos];         t[pos<<1]+=(m-(m>>1))*col[pos];t[pos<<1]%=mod;         t[pos<<1|1]+=(m>>1)*col[pos];t[pos<<1|1]%=mod;         col[pos]=0;     } } void build(int l,int r,int pos) {     col[pos]=0;     if(l==r){t[pos]=w[l]%mod;return ;}//w为重新编号的权值     int m=(l+r)>>1;     build(lson);build(rson);     up(pos); } void update(int L,int R,int x,int l,int r,int pos) {     if(L<=l&&r<=R)     {         t[pos]+=x*(r-l+1);t[pos]%=mod;col[pos]+=x;return ;     }     down(r-l+1,pos);     int m=(l+r)>>1;     if(L<=m)update(L,R,x,lson);     if(R>m)update(L,R,x,rson);     up(pos); } int query(int L,int R,int l,int r,int pos) {     int ans=0;     if(L<=l&&r<=R)return t[pos];     down(r-l+1,pos);     int m=(l+r)>>1;     if(L<=m)ans+=query(L,R,lson),ans%=mod;     if(R>m)ans+=query(L,R,rson),ans%=mod;     up(pos);     return ans; } /////////////////////////////// int dep[N],siz[N],fa[N],son[N],head[M],pos,id[N],top[N],cnt; struct Edge {     int to,nex; }edge[M]; void add(int a,int b) {     edge[++pos].nex=head[a];     edge[pos].to=b;     head[a]=pos; } void dfs1(int x,int f,int deep) {     dep[x]=deep;     fa[x]=f;     siz[x]=1;     int maxson=-1;     for(int i=head[x];i;i=edge[i].nex)     {         int v=edge[i].to;         if(v==f)continue;         dfs1(v,x,deep+1);         siz[x]+=siz[v];         if(siz[v]>maxson)maxson=siz[v],son[x]=v;     } } void dfs2(int x,int topf) {     id[x]=++cnt;     w[cnt]=node[x];     top[x]=topf;     if(!son[x])return;     dfs2(son[x],topf);     for(int i=head[x];i;i=edge[i].nex)     {         int v=edge[i].to;         if(v==fa[x]||v==son[x])continue;         dfs2(v,v);     } } int qrange(int x,int y)//询问x到y最短路径的权值和 {     int ans=0;     while(top[x]!=top[y])     {         if(dep[top[x]]<dep[top[y]])swap(x,y);         ans+=query(id[top[x]],id[x],1,n,1);         ans%=mod;         x=fa[top[x]];     }     if(dep[x]>dep[y])swap(x,y);     ans=(ans+query(id[x],id[y],1,n,1))%mod;     return ans; } void updaterange(int x,int y,int k)//将x 到y的最短路径上加k {     k%=mod;     while(top[x]!=top[y])     {         if(dep[top[x]]<dep[top[y]])swap(x,y);         update(id[top[x]],id[x],k,1,n,1);         x=fa[top[x]];     }     if(dep[x]>dep[y])swap(x,y);     update(id[x],id[y],k,1,n,1); } int qson(int x)//询问以x为根结点的子树去权值和 {     return query(id[x],id[x]+siz[x]-1,1,n,1); } void updateson(int x,int k)//将以x为根结点子树所有点的权值加k {     update(id[x],id[x]+siz[x]-1,k,1,n,1); } int main() {     cin>>n>>m>>root>>mod;     rep(i,1,n)RI(node[i]);     rep(i,1,n-1){int u,v;RII(u,v);add(u,v);add(v,u);}     dfs1(root,0,1);     dfs2(root,root);     build(1,n,1);     rep(i,1,m)     {         int k,x,y,z;RI(k);         if(k==1)         {             RIII(x,y,z);updaterange(x,y,z);         }         else if(k==2)         {             RII(x,y);printf("%d\n",qrange(x,y));         }         else if(k==3)         {             RII(x,y);updateson(x,y);         }         else         {             RI(x);printf("%d\n",qson(x));         }     }     return 0; }
View Code

大佬总结的非常好

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!