题目链接:https://nanti.jisuanke.com/t/A2015
题意:一个树,4中操作,分别是两点间路径的,乘、加、异或、和
题解:对应乘和加,就很简单了,两个laz标记,对于加的直接更新,对于乘的,还要把加的laz也要乘上,那么就是异或了,刚开始没有注意到模数,一直在想分开对于某一位进行标记,但是这个的膜是2^64,那么也就是总共的64位了,这里也要用ull, 因为二进制中 : - x = !x + 1 所以 !x = - x - 1,因为这里用的都是正数ull,溢出的也就相当于膜了,所以直接算就好,这个题原本的时限是3s,但是中石油设的是2s,优化了1个小时也算是过了。。。。
2162ms:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N = 1e5 + 10;
struct edge{
int to, nex;
}e[N * 2];
int n, q;
int head[N], len;
int in[N], son[N], num[N], deep[N], fa[N], pre[N], tot;
void init() {
for(int i = 1; i <= n; i++) {
head[i] = -1;
}
len = 0;
tot = 0;
}
void add(int x, int y) {
e[len].to = y;
e[len].nex = head[x];
head[x] = len++;
}
void dfs1(int u) {
son[u] = -1;
num[u] = 1;
int to;
for(int i = head[u]; i != -1; i = e[i].nex) {
to = e[i].to;
if(to == fa[u]) continue;
deep[to] = deep[u] + 1;
fa[to] = u;
dfs1(to);
num[u] += num[to];
if(son[u] == -1 || num[to] > num[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int rt) {
in[u] = ++tot;
pre[u] = rt;
if(son[u] != -1) {
dfs2(son[u], rt);
}
int to;
for(int i = head[u]; i != -1; i = e[i].nex) {
to = e[i].to;
if(to == fa[u] || to == son[u]) continue;
dfs2(to, to);
}
}
struct node {
int l, r, len;
ll laz1, laz2;
ll sum;
}tree[N << 2];
void build(int l, int r, int cur) {
tree[cur].l = l;
tree[cur].r = r;
tree[cur].len = r - l + 1;
tree[cur].laz1 = 1;
tree[cur].laz2 = 0;
tree[cur].sum = 0;
if(l == r) return;
int mid = (r + l) >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
}
void pushdown(int cur) {
if(tree[cur].laz1 != 1) {
tree[cur << 1].laz1 *= tree[cur].laz1;
tree[cur << 1].laz2 *= tree[cur].laz1;
tree[cur << 1].sum *= tree[cur].laz1;
tree[cur << 1 | 1].laz1 *= tree[cur].laz1;
tree[cur << 1 | 1].laz2 *= tree[cur].laz1;
tree[cur << 1 | 1].sum *= tree[cur].laz1;
tree[cur].laz1 = 1;
}
if(tree[cur].laz2 != 0) {
tree[cur << 1].laz2 += tree[cur].laz2;
tree[cur << 1].sum += tree[cur << 1].len * tree[cur].laz2;
tree[cur << 1 | 1].laz2 += tree[cur].laz2;
tree[cur << 1 | 1].sum += tree[cur << 1 | 1].len * tree[cur].laz2;
tree[cur].laz2 = 0;
}
}
void pushup(int cur) {
tree[cur].sum = tree[cur << 1].sum + tree[cur << 1 | 1].sum;
}
void update(int pl, int pr, int cur, ll val, int op) {
if(pl <= tree[cur].l && tree[cur].r <= pr) {
if(op == 1) {
tree[cur].sum *= val;
tree[cur].laz1 *= val;
tree[cur].laz2 *= val;
} else {
tree[cur].sum += tree[cur].len * val;
tree[cur].laz2 += val;
}
return;
}
pushdown(cur);
if(pl <= tree[cur << 1].r) update(pl, pr, cur << 1, val, op);
if(pr >= tree[cur << 1 | 1].l) update(pl, pr, cur << 1 | 1, val, op);
pushup(cur);
}
void solve (int x, int y, ll val, int op) {
int fx = pre[x], fy = pre[y];
while(fx != fy) {
if(deep[fx] < deep[fy]) {
swap(x, y);
swap(fx, fy);
}
update(in[fx], in[x], 1, val, op);
x = fa[fx];
fx = pre[x];
}
if(deep[x] > deep[y]) swap(x, y);
update(in[x], in[y], 1, val, op);
}
ll query(int pl, int pr, int cur) {
if(pl <= tree[cur].l && tree[cur].r <= pr) {
return tree[cur].sum;
}
ll res = 0;
pushdown(cur);
if(pl <= tree[cur << 1].r) res += query(pl, pr, cur << 1);
if(pr >= tree[cur << 1 | 1].l) res += query(pl, pr, cur << 1 | 1);
return res;
}
ll solvequery(int x, int y) {
int fx = pre[x], fy = pre[y];
ll res = 0;
while(fx != fy) {
if(deep[fx] < deep[fy]) {
swap(x, y);
swap(fx, fy);
}
res += query(in[fx], in[x], 1);
x = fa[fx];
fx = pre[x];
}
if(deep[x] > deep[y]) swap(x, y);
res += query(in[x], in[y], 1);
return res;
}
int main() {
int y;
int op, u, v;
ll x ;
deep[1] = 1;
fa[1] = 0;
while(~scanf("%d", &n)) {
init();
for(int i = 2; i <= n; i++) {
scanf("%d", &y);
add(y, i);
add(i, y);
}
dfs1(1);
dfs2(1, 1);
build(1, n, 1);
scanf("%d", &q);
while(q--) {
scanf("%d %d %d", &op, &u, &v);
if(op == 1) {
scanf("%llu", &x);
solve(u, v, x, 1);
} else if(op == 2) {
scanf("%llu", &x);
solve(u, v, x, 2);
} else if(op == 3) {
solve(u, v, -1, 1);
solve(u, v, -1, 2);
} else {
printf("%llu\n", solvequery(u, v));
}
}
}
return 0;
}
1990ms:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N = 1e5 + 1;
struct edge{
int to, nex;
}e[N * 2];
int n, q;
int head[N], len;
int in[N], son[N], num[N], deep[N], fa[N], pre[N], tot;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void init() {
for(int i = 1; i <= n; i++) {
head[i] = -1;
}
len = 0;
tot = 0;
}
void add(int x, int y) {
e[len].to = y;
e[len].nex = head[x];
head[x] = len++;
}
void dfs1(int u) {
son[u] = -1;
num[u] = 1;
int to;
for(int i = head[u]; i != -1; i = e[i].nex) {
to = e[i].to;
if(to == fa[u]) continue;
deep[to] = deep[u] + 1;
fa[to] = u;
dfs1(to);
num[u] += num[to];
if(son[u] == -1 || num[to] > num[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int rt) {
in[u] = ++tot;
pre[u] = rt;
if(son[u] != -1) {
dfs2(son[u], rt);
}
int to;
for(int i = head[u]; i != -1; i = e[i].nex) {
to = e[i].to;
if(to == fa[u] || to == son[u]) continue;
dfs2(to, to);
}
}
struct node {
int l, r, len;
ll laz1, laz2;
ll sum;
}tree[N << 2];
void build(int l, int r, int cur) {
tree[cur].l = l;
tree[cur].r = r;
tree[cur].len = r - l + 1;
tree[cur].laz1 = 1;
tree[cur].laz2 = 0;
tree[cur].sum = 0;
if(l == r) return;
int mid = (r + l) >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
}
void pushdown(int cur) {
if(tree[cur].laz1 != 1) {
tree[cur << 1].laz1 *= tree[cur].laz1;
tree[cur << 1].laz2 *= tree[cur].laz1;
tree[cur << 1].sum *= tree[cur].laz1;
tree[cur << 1 | 1].laz1 *= tree[cur].laz1;
tree[cur << 1 | 1].laz2 *= tree[cur].laz1;
tree[cur << 1 | 1].sum *= tree[cur].laz1;
tree[cur].laz1 = 1;
}
if(tree[cur].laz2) {
tree[cur << 1].laz2 += tree[cur].laz2;
tree[cur << 1].sum += tree[cur << 1].len * tree[cur].laz2;
tree[cur << 1 | 1].laz2 += tree[cur].laz2;
tree[cur << 1 | 1].sum += tree[cur << 1 | 1].len * tree[cur].laz2;
tree[cur].laz2 = 0;
}
}
void pushup(int cur) {
tree[cur].sum = tree[cur << 1].sum + tree[cur << 1 | 1].sum;
}
int opp;
ll val;
void update(int pl, int pr, int cur) {
if(pl <= tree[cur].l && tree[cur].r <= pr) {
if(opp == 1) {
tree[cur].sum *= val;
tree[cur].laz1 *= val;
tree[cur].laz2 *= val;
} else {
tree[cur].sum += tree[cur].len * val;
tree[cur].laz2 += val;
}
return;
}
pushdown(cur);
if(pl <= tree[cur << 1].r) update(pl, pr, cur << 1);
if(pr >= tree[cur << 1 | 1].l) update(pl, pr, cur << 1 | 1);
pushup(cur);
}
int fx, fy;
void solve (int x, int y) {
fx = pre[x], fy = pre[y];
while(fx != fy) {
if(deep[fx] < deep[fy]) {
x ^= y ^= x ^= y;
fx ^= fy ^= fx ^= fy;
}
update(in[fx], in[x], 1);
x = fa[fx];
fx = pre[x];
}
if(deep[x] > deep[y]) x ^= y ^= x ^= y;;
update(in[x], in[y], 1);
}
ll query(int pl, int pr, int cur) {
if(pl <= tree[cur].l && tree[cur].r <= pr) {
return tree[cur].sum;
}
ll res = 0;
pushdown(cur);
if(pl <= tree[cur << 1].r) res += query(pl, pr, cur << 1);
if(pr >= tree[cur << 1 | 1].l) res += query(pl, pr, cur << 1 | 1);
return res;
}
ll solvequery(int x, int y) {
fx = pre[x], fy = pre[y];
ll res = 0;
while(fx != fy) {
if(deep[fx] < deep[fy]) {
x ^= y ^= x ^= y;
fx ^= fy ^= fx ^= fy;
}
res += query(in[fx], in[x], 1);
x = fa[fx];
fx = pre[x];
}
if(deep[x] > deep[y]) x ^= y ^= x ^= y;
res += query(in[x], in[y], 1);
return res;
}
int main() {
int y;
int op, u, v;
ll x ;
while(~scanf("%d", &n)) {
init();
for(int i = 2; i <= n; i++) {
y = read();
add(y, i);
add(i, y);
}
dfs1(1);
dfs2(1, 1);
build(1, n, 1);
q = read();
while(q--) {
op = read();
u = read();
v = read();
if(op == 1) {
x = read();
opp = 1;
val = x;
solve(u, v);
} else if(op == 2) {
x = read();
opp = 2;
val = x;
solve(u, v);
} else if(op == 3) {
opp = 1;
val = -1;
solve(u, v);
opp = 2;
solve(u, v);
} else {
printf("%llu\n", solvequery(u, v));
}
}
}
return 0;
}