#ifndef NOSTDCPP #include <bits/stdc++.h> #else #include <algorithm> #include <bitset> #include <cassert> #include <climits> #include <complex> #include <cstring> #include <cstdio> #include <deque> #include <exception> #include <functional> #include <iomanip> #include <iostream> #include <istream> #include <iterator> #include <list> #include <map> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> #endif # ifdef Linux_System # define getchar getchar_unlocked # define putchar putchar_unlocked # endif # define RESET(_) memset(_, 0, sizeof(_)) # define RESET_(_, val) memset(_, val, sizeof(_)) # define fi first # define se second # define pb push_back # define midf(x, y) ((x + y) >> 1) # define DXA(_) ((_ << 1)) # define DXB(_) ((_ << 1) | 1) # define next __Chtholly__ # define x1 __Mercury__ # define y1 __bbtl04__ # define index __ikooo__ using namespace std; typedef unsigned long long ll; typedef vector <int> vi; typedef set <int> si; typedef pair <int, int> pii; typedef long double ld; const int MOD = 1e9 + 7; const int maxn = 300009; const int maxm = 300009; const double pi = acos(-1.0); const double eps = 1e-6; ll myrand(ll mod){return ((ll)rand() << 32 ^ (ll)rand() << 16 ^ rand()) % mod;} template <class T> inline bool scan_d(T & ret) { char c; int sgn; if(c = getchar(), c == EOF)return false; while(c != '-' && (c < '0' || c > '9'))c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return true; } #ifdef Cpp11 template <class T, class ... Args> inline bool scan_d(T & ret, Args & ... args) { scan_d(ret); scan_d(args...); } #define cin.tie(0); cin.tie(nullptr); #define cout.tie(0); cout.tie(nullptr); #endif inline bool scan_ch(char &ch) { if(ch = getchar(), ch == EOF)return false; while(ch == ' ' || ch == '\n')ch = getchar(); return true; } inline void out_number(ll x) { if(x < 0) { putchar('-'); out_number(- x); return ; } if(x > 9)out_number(x / 10); putchar(x % 10 + '0'); } struct node { ll sum, add, mul; }tree[maxn]; void pushup(int p, int l, int r) { tree[p].sum = tree[DXA(p)].sum + tree[DXB(p)].sum; } void pre(int l, int r, int p) { tree[p].add = 0; tree[p].mul = 1; tree[p].sum = 0; if(l == r) { return ; } int mid = midf(l, r); pre(l, mid, DXA(p)); pre(mid + 1, r, DXB(p)); } void pushdown(int p, int l, int r) { if(tree[p].add == 0 && tree[p].mul == 1)return ; int mid = midf(l, r); tree[DXA(p)].add = (tree[DXA(p)].add * tree[p].mul + tree[p].add); tree[DXB(p)].add = (tree[DXB(p)].add * tree[p].mul + tree[p].add); tree[DXA(p)].mul = (tree[p].mul * tree[DXA(p)].mul); tree[DXB(p)].mul = (tree[p].mul * tree[DXB(p)].mul); tree[DXA(p)].sum = (tree[DXA(p)].sum * tree[p].mul + (mid - l + 1) * tree[p].add); tree[DXB(p)].sum = (tree[DXB(p)].sum * tree[p].mul + (r - mid) * tree[p].add); tree[p].add = 0; tree[p].mul = 1; } int l, r; ll val; void update_add(int nl, int nr, int p) { if(l <= nl && nr <= r) { tree[p].add = (tree[p].add + val); tree[p].sum = ((nr - nl + 1) * val + tree[p].sum); return ; } pushdown(p, nl, nr); int mid = midf(nl, nr); if(l <= mid)update_add(nl, mid, DXA(p)); if(mid < r) update_add(mid + 1, nr, DXB(p)); pushup(p, nl, nr); } void update_mul(int nl, int nr, int p) { if(l <= nl && nr <= r) { tree[p].mul = (tree[p].mul * val); tree[p].add = (tree[p].add * val); tree[p].sum = (tree[p].sum * val); return ; } pushdown(p, nl, nr); int mid = midf(nl, nr); if(l <= mid)update_mul(nl, mid, DXA(p)); if(mid < r) update_mul(mid + 1, nr, DXB(p)); pushup(p, nl, nr); } ll query(int nl, int nr, int p) { if(l <= nl && nr <= r) return tree[p].sum; pushdown(p, nl, nr); int mid = midf(nl, nr); ll ans = 0; if(l <= mid) ans += query(nl, mid, DXA(p)); if(mid < r) ans += query(mid + 1, nr, DXB(p)); return ans; } int n, m, type; int v[maxm], prevv[maxm]; int info[maxn], deep[maxn], size[maxn]; int father[maxn], head[maxn], len[maxn], son[maxn], id[maxn], pid[maxn]; bool vis[maxn]; int ans, cnt; int N, nedge; struct edg { int f, t, cost; }edge[maxn]; inline void insert(int x, int y) { ++ nedge; v[nedge] = y; prevv[nedge] = info[x]; info[x] = nedge; } void dfs1(int u, int pre, int d) { deep[u] = d; father[u] = pre; son[u] = 0; size[u] = 1; for(int i = info[u]; i; i = prevv[i]) { if(v[i] != pre) { dfs1(v[i], u, d + 1); size[u] += size[v[i]]; if(! son[u] || size[v[i]] > size[son[u]]) son[u] = v[i]; } } } void getpos(int u, int sp) { head[u] = sp; id[u] = ++ cnt; pid[id[u]] = cnt; if(son[u]) getpos(son[u], sp); for(int i = info[u]; i; i = prevv[i]) { if(v[i] != son[u] && v[i] != father[u]) getpos(v[i], v[i]); } } void init() { RESET(info); RESET(prevv); RESET_(deep, -1); RESET(size); RESET(father); RESET(head); RESET(len); RESET(son); RESET(id); RESET(pid); RESET(v); cnt = 0; nedge = 0; } void __add__(int u, int v) { int f1 = head[u], f2 = head[v]; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1,f2); swap(u,v); } l = id[f1], r = id[u]; update_add(1, n, 1); u = father[f1]; f1 = head[u]; } if(deep[u] > deep[v]) swap(u, v); l = id[u], r = id[v]; update_add(1, n, 1); } void __mul__(int u, int v) { int f1 = head[u], f2 = head[v]; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1,f2); swap(u,v); } l = id[f1], r = id[u]; update_mul(1, n, 1); u = father[f1]; f1 = head[u]; } if(deep[u] > deep[v]) swap(u, v); l = id[u], r = id[v]; update_mul(1, n, 1); } ll __query__(int u, int v) { int f1 = head[u], f2 = head[v]; ll ans = 0; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1,f2); swap(u,v); } l = id[f1], r = id[u]; ans += query(1, n, 1); u = father[f1]; f1 = head[u]; } if(deep[u] > deep[v]) swap(u, v); l = id[u], r = id[v]; ans += query(1, n, 1); return ans; } int main() { int f, t; while(~ scanf("%d", &n)) { init(); pre(1, n, 1); for(int i = 2; i <= n; ++ i) { scanf("%d", &r); insert(i, r); insert(r, i); } dfs1(1, -1, 0); getpos(1, 1); scanf("%d", &m); while(m --) { scanf("%d", &type); switch(type) { case 1: scanf("%d %d %llu", &l, &r, &val); __mul__(l, r); break; case 2: scanf("%d %d %llu", &l, &r, &val); __add__(l, r); break; case 3: scanf("%d %d", &f, &t); val = -1; __mul__(f, t); __add__(f, t); break; case 4: scanf("%d %d", &l, &r); printf("%llu\n", __query__(l, r)); break; default: break; } } } return 0; }
|