# 树链剖分模板

1 #include<cstdio>
2 #include<iostream>
3 #include<vector>
4 #define tx top[x]
5 #define ty top[y]
6 #define ls o<<1
7 #define rs o<<1|1
8 #define M ((L+R)>>1)
9 using namespace std;
10 const int maxn = 100010;
11
12 int n, m, P ,root, tot;
13 int A[maxn], fa[maxn], deep[maxn], num[maxn], son[maxn], ID[maxn], top[maxn], fID[maxn];
15 vector<int> G[maxn];
16
17 void addedge(int x,int y) {
18     G[x].push_back(y);
19 }
20
21 int dfs1(int x,int dep) { //返回包括自己，子树的大小
22     deep[x] = dep;
23     int ret = 1;
24     int len = G[x].size();
25     int MX = 0;
26     for(int i = 0;i < len;i++) {
27         int tp = G[x][i];
28         if(fa[x] == tp) continue;
29         fa[tp] = x;
30         int back = dfs1(tp,dep+1);
31         if(back > MX) {
32             son[x] = tp;
33             MX = back;
34         }
35         ret += back;
36     }
37     num[x] = ret;
38     return ret;
39 }
40
41 void dfs2(int x) {
42     if(x == 0) return;
43     ID[x] = ++tot;
44     fID[tot] = x;
45     if(son[fa[x]] == x) top[x] = top[fa[x]];
46     else top[x] = x;
47     int len = G[x].size();
48     dfs2(son[x]);
49     for(int i = 0;i < len;i++) {
50         int tp = G[x][i];
51         if(tp != fa[x] && tp != son[x]) dfs2(tp);
52     }
53 }
54
55 inline void build(int o,int L,int R) {
56     if(L == R) {
57         sumv[o] = A[fID[L]]%P;
58         return;
59     }
60     build(ls,L,M);
61     build(rs,M+1,R);
62     sumv[o] = (sumv[ls] + sumv[rs])%P;
63 }
64
65 inline void pushdown(int o,int L,int R) {
71 }
72
73 int ql,qr,qa;
74 inline void update(int o,int L,int R) {
75     if(ql <= L && R <= qr) {
77         (sumv[o] += qa*(R-L+1))%=P;
78         return;
79     }
80     pushdown(o,L,R);
81     if(ql <= M) update(ls,L,M);
82     if(qr > M) update(rs,M+1,R);
83     sumv[o] = (sumv[ls] + sumv[rs])%P;
84 }
85
86 inline int query(int o,int L,int R) {
87     if(ql <= L && R <= qr) return sumv[o]%P;
88     int ret = 0;
89     pushdown(o,L,R);
90     if(ql <= M) (ret += query(ls,L,M))%=P;
91     if(qr > M) (ret += query(rs,M+1,R))%=P;
92     return ret%P;
93 }
94
95
96 int LCA(int x,int y) {
97     int ret = 0;
98     while(tx != ty) {
99         if(deep[tx] >= deep[ty]) {
100             //x 走到 top[x]（编号小） 的 爸爸 ,top[x] 的爸爸是轻链
101             ql = ID[tx], qr = ID[x];//下闭上开
102             (ret += query(1,1,n))%=P;
103             x = fa[tx];
104         }
105         else {
106             ql = ID[ty], qr = ID[y];
107             (ret += query(1,1,n))%=P;
108             y = fa[ty];
109         }
110     }
111
112     if(x == y) {
113         ql = ID[x],qr = ql;
114         (ret += query(1,1,n))%=P;
115         return ret;
116     }
117      if(deep[x] > deep[y]) swap(x,y);
118     ql = ID[x], qr = ID[y];
119      (ret += query(1,1,n))%=P;
120   return ret;
121 }
122
123 void LCA_add(int x,int y,int k) {
124     qa = k%P;
125     while(tx != ty) {
126         if(deep[tx] >= deep[ty]) {
127             //x 走到 top[x]（编号小） 的 爸爸 ,top[x] 的爸爸是轻链
128             ql = ID[tx], qr = ID[x];//下闭上开
129             update(1,1,n);
130             x = fa[tx];
131         }
132         else {
133             ql = ID[ty], qr = ID[y];
134             update(1,1,n);
135             y = fa[ty];
136         }
137     }
138
139     if(x == y) {
140         ql = ID[x],qr = ql;
141         update(1,1,n);
142         return;
143     }
144      if(deep[x] > deep[y]) swap(x,y);
145     ql = ID[x], qr = ID[y];
146      update(1,1,n);
147 }
148
149 int main() {
150     scanf("%d %d %d %d",&n, &m, &root, &P);
151     for(int i = 1;i <= n;i++) scanf("%d",A+i);
152     for(int i = 1,x,y;i < n;i++) {
153         scanf("%d%d",&x,&y);
156     }
157
158     dfs1(root,1);
159     dfs2(root);
160     build(1,1,n);
161
162     for(int i = 1,x,l,r,z;i <= m;i++) {
163         scanf("%d",&x);
164         if(x == 1) {
165             scanf("%d%d%d",&l,&r,&z);
167         } else if(x == 2) {
168             scanf("%d%d",&l,&r);
169             printf("%d\n",LCA(l,r));
170         } else if(x == 3) {
171             scanf("%d%d",&l,&z);
172             ql = ID[l],qr = ql+num[l]-1,qa=z;
173             update(1,1,n);
174         } else {
175             scanf("%d",&z);
176             ql = ID[z],qr = ql + num[z]-1;
177             printf("%d\n",query(1,1,n));
178         }
179     }
180     return 0;
181 }

posted @ 2018-08-25 10:22  Frank的成长之路  阅读(189)  评论(0编辑  收藏  举报