重链剖分模板

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define maxn 100010
  6 
  7 using namespace std;
  8 
  9 struct node
 10 {
 11     int ed,nxt;
 12 };
 13 node edge[maxn<<1];
 14 int n,m,root,cnt,first[maxn],p;
 15 int fa[maxn],siz[maxn],son[maxn],dep[maxn];
 16 int rnk[maxn],seg[maxn],top[maxn],rnk_cnt;
 17 int num[maxn],num_rnk[maxn],tree[maxn<<2],tag[maxn<<2],ans,tot;
 18 
 19 inline void add_edge(int s,int e)
 20 {
 21     ++cnt;
 22     edge[cnt].ed=e;
 23     edge[cnt].nxt=first[s];
 24     first[s]=cnt;
 25     return;
 26 }
 27 
 28 inline void dfs_1(int now,int pre)
 29 {
 30     dep[now]=dep[pre]+1; fa[now]=pre; siz[now]=1;
 31     for(register int i=first[now];i;i=edge[i].nxt)
 32     {
 33         int e=edge[i].ed;
 34         if(e==pre) continue;
 35         dfs_1(e,now);
 36         siz[now]+=siz[e];
 37         if(son[now]==-1||siz[e]>siz[son[now]]) son[now]=e;
 38     }
 39     return;
 40 }
 41 
 42 inline void dfs_2(int now,int heavy_fa)
 43 {
 44     ++rnk_cnt;
 45     rnk[now]=rnk_cnt; seg[rnk_cnt]=now; top[now]=heavy_fa;num_rnk[rnk_cnt]=num[now];
 46     if(son[now]==-1) return;
 47     dfs_2(son[now],heavy_fa);
 48     for(register int i=first[now];i;i=edge[i].nxt)
 49     {
 50         int e=edge[i].ed;
 51         if(e!=fa[now]&&e!=son[now]) dfs_2(e,e);
 52     }
 53     return;
 54 }
 55 
 56 inline void build(int k,int l,int r)
 57 {
 58     if(l==r)
 59     {
 60         tree[k]=num_rnk[l]%p;
 61         return;
 62     }
 63     int mid=(l+r)>>1,son=k<<1;
 64     build(son,l,mid); build(son|1,mid+1,r);
 65     tree[k]=(tree[son]+tree[son|1])%p;
 66     return;
 67 }
 68 
 69 inline void push_down(int k,int l,int r)
 70 {
 71     int mid=(l+r)>>1,son=k<<1;
 72     tree[son]=(tree[son]+(mid-l+1)*tag[k])%p; tag[son]=(tag[son]+tag[k])%p;
 73     tree[son|1]=(tree[son|1]+(r-mid)*tag[k])%p; tag[son|1]=(tag[son|1]+tag[k])%p;
 74     tag[k]=0;
 75     return;
 76 }
 77 
 78 inline void modify(int k,int l,int r,int x,int y,int v)
 79 {
 80     if(r<x||l>y) return;
 81     if(x<=l&&r<=y)
 82     {
 83         tree[k]=(tree[k]+v*(r-l+1))%p;
 84         tag[k]=(tag[k]+v)%p;
 85         return;
 86     }
 87     if(tag[k]) push_down(k,l,r);
 88     int mid=(l+r)>>1,son=k<<1;
 89     modify(son,l,mid,x,y,v); modify(son|1,mid+1,r,x,y,v);
 90     tree[k]=(tree[son]+tree[son|1])%p;
 91     return;
 92 }
 93 
 94 
 95 inline void modify_tree(int x,int y,int v)
 96 {
 97     while(top[x]!=top[y])
 98     {
 99         if(dep[top[x]]<dep[top[y]]) swap(x,y);
100         modify(1,1,n,rnk[top[x]],rnk[x],v);
101         x=fa[top[x]];
102     }
103     modify(1,1,n,min(rnk[x],rnk[y]),max(rnk[x],rnk[y]),v);
104     return;
105 }
106 
107 inline void get_sum(int k,int l,int r,int x,int y)
108 {
109     if(r<x||l>y) return;
110     if(x<=l&&r<=y)
111     {
112         tot=(tot+tree[k])%p;
113         return;
114     }
115     if(tag[k]) push_down(k,l,r);
116     int mid=(l+r)>>1,son=k<<1;
117     get_sum(son,l,mid,x,y); get_sum(son|1,mid+1,r,x,y);
118     tree[k]=(tree[son]+tree[son|1])%p;
119     return;
120 }
121 
122 inline void tree_sum(int x,int y)
123 {
124     while(top[x]!=top[y])
125     {
126         if(dep[top[x]]<dep[top[y]]) swap(x,y);
127         tot=0;
128         get_sum(1,1,n,rnk[top[x]],rnk[x]);
129         ans=(ans+tot)%p;
130         x=fa[top[x]];
131     }
132     tot=0;
133     get_sum(1,1,n,min(rnk[x],rnk[y]),max(rnk[x],rnk[y]));
134     ans=(ans+tot)%p;
135     return;
136 }
137 
138 int main()
139 {
140     scanf("%d%d%d%d",&n,&m,&root,&p);
141     for(register int i=1;i<=n;++i)
142         scanf("%d",&num[i]);
143     for(register int i=1;i<=n-1;++i)
144     {
145         int s,e;
146         scanf("%d%d",&s,&e);
147         add_edge(s,e);
148         add_edge(e,s);
149     }
150     memset(son,-1,sizeof(son));
151     dfs_1(root,0);
152     dfs_2(root,root);
153     build(1,1,n);
154     for(register int i=1;i<=m;++i)
155     {
156         int opt;
157         scanf("%d",&opt);
158         if(opt==1)
159         {
160             int x,y,v;
161             scanf("%d%d%d",&x,&y,&v);
162             modify_tree(x,y,v%p);
163         }
164         else if(opt==2)
165         {
166             int x,y;
167             ans=0;
168             scanf("%d%d",&x,&y);
169             tree_sum(x,y);
170             printf("%d
",ans%p); 
171         }
172         else if (opt==3)
173         {
174             int x,v;
175             scanf("%d%d",&x,&v);
176             modify(1,1,n,rnk[x],rnk[x]+siz[x]-1,v%p);
177         }
178         else if(opt==4)
179         {
180             int x;
181             scanf("%d",&x);
182             tot=0;
183             //printf("%d %d
",rnk[x],rnk[x]+siz[x]-1);
184             get_sum(1,1,n,rnk[x],rnk[x]+siz[x]-1);
185             printf("%d
",tot%p);
186         }
187     }
188     return 0;
189 } 

Orz

原文地址:https://www.cnblogs.com/Hoyoak/p/11813241.html