重链剖分模板
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\n",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\n",rnk[x],rnk[x]+siz[x]-1); 184 get_sum(1,1,n,rnk[x],rnk[x]+siz[x]-1); 185 printf("%d\n",tot%p); 186 } 187 } 188 return 0; 189 }
Orz