【中石大2019年我能变强组队训练赛热身赛20190802】E

Description

给定一棵树和若干次操作,树上节点的权值一开始都是0,要求完成如下操作:

令x,y两点间路径上点的点权都乘上一个数

令x,y两点间路径上点的点权都加上一个数

令x,y两点间路径上点的点权都按位取反(~)

查询两点间路径上点的点权之和

所有答案均对$2^{64}$取模

Solution

树链剖分的题目。

关于对$2^{64}$取模,我们不妨将数组定为unsigned long long类型,这样自然溢出就实现了对这个数的取模。

关于前两个操作我们维护两个标记即可完成,

关于对第三个操作,即按位取反操作,我们不妨思考一下按位取反的实现过程,即~x=1111111...1-x,也就是我们将这个操作转换成*(-1)+unsigned long long的最大值即可

Code

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef unsigned long long ll;
  4 struct node {
  5     int next, to;
  6 } e[200010 << 1];
  7 int num, head[200010];
  8 inline void add(int from, int to) {
  9     e[++num].next = head[from];
 10     e[num].to = to;
 11     head[from] = num;
 12 }
 13 int top[200010], fa[200010], dep[200010], size[200010], son[200010], dfn[200010], cnt;
 14 void dfs1(int now, int f, int d) {
 15     dep[now] = d;
 16     fa[now] = f;
 17     size[now] = 1;
 18     for (register int i = head[now]; i; i = e[i].next) 
 19         if (e[i].to != f) {
 20             dfs1(e[i].to, now, d + 1);
 21             size[now] += size[e[i].to];
 22             if (size[son[now]] < size[e[i].to]) son[now] = e[i].to;
 23         }
 24 }
 25 void dfs2(int now, int f) {
 26     top[now] = f;
 27     dfn[now] = ++cnt;
 28     if (son[now]) dfs2(son[now], f);
 29     for (register int i = head[now]; i; i = e[i].next)
 30         if (e[i].to != son[now] && e[i].to != fa[now]) dfs2(e[i].to, e[i].to);
 31 }
 32 ll sum[200010 << 2];
 33 ll addtag[200010 << 2];
 34 ll addmul[200010 << 2];
 35 int n;
 36 void build(int now, int l, int r) {
 37     sum[now] = addtag[now] = 0;
 38     addmul[now] = 1;
 39     if (l == r) return ;
 40     int mid = l + r >> 1;
 41     build(now << 1, l, mid);
 42     build(now << 1 | 1, mid + 1, r);
 43 }
 44 void pushup(int now) {
 45     sum[now] = sum[now << 1] + sum[now << 1 | 1];
 46 }
 47 void pushdown(int now, ll l, ll r) {
 48     if (addmul[now] != 1) {
 49         sum[now << 1] *= addmul[now];
 50         addmul[now << 1] *= addmul[now];
 51         addtag[now << 1] *= addmul[now];
 52         sum[now << 1 | 1] *= addmul[now];
 53         addmul[now << 1 | 1] *= addmul[now];
 54         addtag[now << 1 | 1] *= addmul[now];      
 55         addmul[now] = 1;
 56     }
 57     if (addtag[now]) {
 58         sum[now << 1] += addtag[now] * l;
 59         addtag[now << 1] += addtag[now];
 60         sum[now << 1 | 1] += addtag[now] * r;
 61         addtag[now << 1 | 1] += addtag[now];      
 62         addtag[now] = 0;
 63     }
 64 }
 65 void updateadd(int now, int l, int r, int x, int y, ll val) {
 66     if (x <= l && r <= y) {
 67         sum[now] += val * (r - l + 1);
 68         addtag[now] += val;
 69         return ;
 70     }
 71     int mid = l + r >> 1;
 72     pushdown(now, mid - l + 1, r - mid);
 73     if (x <= mid) updateadd(now << 1, l, mid, x, y, val);
 74     if (y > mid) updateadd(now << 1 | 1, mid + 1, r, x, y, val);
 75     pushup(now); 
 76 } 
 77 void updatemul(int now, int l, int r, int x, int y, ll val) {
 78     if (x <= l && r <= y) {
 79         sum[now] *= val;
 80         addtag[now] *= val;
 81         addmul[now] *= val;
 82         return ;
 83     }
 84     int mid = l + r >> 1;
 85     pushdown(now, mid - l + 1, r - mid);
 86     if (x <= mid) updatemul(now << 1, l, mid, x, y, val);
 87     if (y > mid) updatemul(now << 1 | 1, mid + 1, r, x, y, val);
 88     pushup(now);    
 89 }
 90 ll query(int now, int l, int r, int x, int y) {
 91     if (x <= l && r <= y) return sum[now];
 92     int mid = l + r >> 1;
 93     pushdown(now, mid - l + 1, r - mid);
 94     ll ret = 0;
 95     if (x <= mid) ret += query(now << 1, l, mid, x, y);
 96     if (y > mid) ret += query(now << 1 | 1, mid + 1, r, x, y);
 97     return ret;
 98 }
 99 void updateadd(int from, int to, ll val) {
100     while (top[from] != top[to]) {
101         if (dep[top[from]] < dep[top[to]]) swap(from, to);
102         updateadd(1, 1, n, dfn[top[from]], dfn[from], val);
103         from = fa[top[from]];
104     }
105     if (dep[from] > dep[to]) swap(from, to);
106     updateadd(1, 1, n, dfn[from], dfn[to], val);
107 }
108 void updatemul(int from, int to, ll val) {
109     while (top[from] != top[to]) {
110         if (dep[top[from]] < dep[top[to]]) swap(from, to);
111         updatemul(1, 1, n, dfn[top[from]], dfn[from], val);
112         from = fa[top[from]];
113     }
114     if (dep[from] > dep[to]) swap(from, to);
115     updatemul(1, 1, n, dfn[from], dfn[to], val);    
116 }
117 ll query(int from, int to) {
118     ll ret = 0;
119     while (top[from] != top[to]) {
120         if (dep[top[from]] < dep[top[to]]) swap(from, to);
121         ret += query(1, 1, n, dfn[top[from]], dfn[from]);
122         from = fa[top[from]];
123     }
124     if (dep[from] > dep[to]) swap(from, to);
125     ret += query(1, 1, n, dfn[from], dfn[to]);  
126     return ret;
127 }
128 ll SHLAK = 18446744073709551615;
129 int main() {
130     while (~scanf("%d", &n)) {
131         cnt = 0; num = 0;
132         memset(head, 0, sizeof(head));
133         memset(son, 0, sizeof(son));
134         for (register int i = 2; i <= n; ++i) {
135             int x; scanf("%d", &x);
136             add(x, i); add(i, x);
137         }
138         dfs1(1, 0, 0);
139         dfs2(1, 1);
140         build(1, 1, n);
141         int m;
142         scanf("%d", &m);
143         for (register int i = 1; i <= m; ++i) {
144             int op, x, y;
145             ll z;
146             scanf("%d%d%d", &op, &x, &y);
147             if (op == 1) {
148                 scanf("%llu", &z);
149                 updatemul(x, y, z);
150             }
151             else if (op == 2) {
152                 scanf("%llu", &z);
153                 updateadd(x, y, z);             
154             }
155             else if (op == 3) {
156                 updatemul(x, y, -1);
157                 updateadd(x, y, SHLAK);
158             }
159             else {
160                 printf("%llu\n", query(x, y));
161             }
162         }
163     }
164     return 0;
165 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/11291129.html