传送门:https://nanti.jisuanke.com/t/31714
题意:
给一棵树,每个结点有一个值val,初始为0,有4个操作。
1:从u到v,每个结点更新为 val * x
2:从u到v,每个结点更新为 val + x
3:从u到v,每个结点更新为 ~val
4:输出从u到v路径上的和,对 2^64 取模
思路:
先树剖一下,用线段树维护。然后1、2、4操作都很常规。
对于操作3,考虑 ~a = 2^64 - 1 - a,然后因为要模 2^64,所以实际上就变为 ~a = - a -1,那么先 * (-1),变为 - a,再 -1,就成了 - a - 1,也就是 ~a。这样的话等于都是1、2、4操作了,然后就变成模板题了。。。
模 2^64的话ull直接算就可以了。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;
const ll M = 1e9 + 7;
const ll INF = 1e15;
const int N = 4010;
const double _e = 10e-6;
const int maxn = 1e5 + 10;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };
int x, y;
ull val;
int n, m;
int e_max, beg[maxn * 2], nex[maxn * 2], to[maxn * 2];
int cnt, siz[maxn], top[maxn], son[maxn], height[maxn], fa[maxn], nid[maxn], id[maxn];
ull summ[maxn * 4], lazy1[maxn * 4], lazy2[maxn * 4];
void push_up(int id)
{
summ[id] = summ[ls] + summ[rs];
}
void push_down(int id, int ln, int rn)
{
if (lazy2[id] != 1) {
summ[ls] *= lazy2[id]; summ[rs] *= lazy2[id];
lazy1[ls] *= lazy2[id]; lazy1[rs] *= lazy2[id];
lazy2[ls] *= lazy2[id]; lazy2[rs] *= lazy2[id];
lazy2[id] = 1;
}
if (lazy1[id] != 0) {
summ[ls] += lazy1[id] * ln; summ[rs] += lazy1[id] * rn;
lazy1[ls] += lazy1[id]; lazy1[rs] += lazy1[id];
lazy1[id] = 0;
}
}
void update(int id, int l, int r, int _l, int _r, ull v,int type)
{
if (l == _l&&r == _r) {
if (type == 1) {
summ[id] *= v;
lazy1[id] *= v;
lazy2[id] *= v;
}
else if (type == 2) {
summ[id] += v*(r - l + 1);
lazy1[id] += v;
}
return;
}
int mid = (l + r) / 2;
push_down(id, mid - l + 1, r - mid);
if (_r <= mid)
update(lson, _l, _r, v, type);
else if (_l > mid)
update(rson, _l, _r, v, type);
else {
update(lson, _l, mid, v, type);
update(rson, mid + 1, _r, v, type);
}
push_up(id);
}
ull query(int id, int l, int r, int _l, int _r)
{
if (l == _l&&r == _r)
return summ[id];
int mid = (l + r) / 2;
push_down(id, mid - l + 1, r - mid);
ull ans = 0;
if (_r <= mid)
ans += query(lson, _l, _r);
else if (_l > mid)
ans += query(rson, _l, _r);
else
ans += query(lson, _l, mid) + query(rson, mid + 1, _r);
push_up(id);
return ans;
}
void add(int x, int y)
{
to[++e_max] = y;
nex[e_max] = beg[x];
beg[x] = e_max;
}
void dfs1(int u, int father, int depth)
{
height[u] = depth; fa[u] = father; siz[u] = 1;
for (int i = beg[u]; ~i; i = nex[i]) {
int v = to[i];
if (v != fa[u]) {
dfs1(v, u, depth + 1);
siz[u] += siz[v];
if (son[u] == -1 || siz[v] > siz[son[u]])
son[u] = v;
}
}
}
void dfs2(int u, int t)
{
top[u] = t; nid[u] = ++cnt; id[cnt] = u;
if (son[u] == -1) return;
dfs2(son[u], t);
for (int i = beg[u]; ~i; i = nex[i]) {
int v = to[i];
if (v != son[u] && v != fa[u])
dfs2(v, v);
}
}
void init()
{
cnt = 0; e_max = 0;
memset(son, -1, sizeof(son)); memset(beg, -1, sizeof(beg));
}
ull query_path(int l, int r) {
ull ans = 0;
int fl = top[l], fr = top[r];
while (fl != fr) {
if (height[fl] >= height[fr]) {
ans += query(1, 1, n, nid[fl], nid[l]);
l = fa[fl];
}
else {
ans += query(1, 1, n, nid[fr], nid[r]);
r = fa[fr];
}
fl = top[l], fr = top[r];
}
if (nid[l] < nid[r])
ans += query(1, 1, n, nid[l], nid[r]);
else
ans += query(1, 1, n, nid[r], nid[l]);
return ans;
}
void update_path(int l, int r, ull val, int type)
{
int fl = top[l], fr = top[r];
while (fl != fr) {
if (height[fl] > height[fr]) {
update(1, 1, n, nid[fl], nid[l], val, type);
l = fa[fl];
}
else {
update(1, 1, n, nid[fr], nid[r], val, type);
r = fa[fr];
}
fl = top[l], fr = top[r];
}
if (nid[l] <= nid[r]) update(1, 1, n, nid[l], nid[r], val, type);
else update(1, 1, n, nid[r], nid[l], val, type);
}
int main()
{
while (~scanf("%d", &n)) {
init(); cl0(summ); cl0(lazy1);
fill(lazy2, lazy2 + maxn * 4, 1);
for (int i = 2; i <= n; i++) {
scanf("%d", &x);
add(x, i); add(i, x);
}
dfs1(1, 1, 1); dfs2(1, 1);
scanf("%d", &m);
int type;
while (m--) {
scanf("%d", &type);
if (type == 1) {
scanf("%d%d%llu", &x, &y, &val);
update_path(x, y, val, 1);
}
else if (type == 2) {
scanf("%d%d%llu", &x, &y, &val);
update_path(x, y, val, 2);
}
else if (type == 3) {
scanf("%d%d", &x, &y);
update_path(x, y, -1, 1);
update_path(x, y, -1, 2);
}
else {
scanf("%d%d", &x, &y);
printf("%llu\n", query_path(x, y));
}
}
}
return 0;
}