You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she will be queen of Tusikur, so she wanted to travel the world while she was still young. In a country, she found a small pub called Whitehouse. Just as she was about to go in for a drink, the boss Carola appeared. And ask her to solve this problem or she will not be allowed to enter the pub. The problem description is as follows:
There is a tree with nn nodes, each node ii contains weight a[i]a[i], the initial value of a[i]a[i] is 00. The root number of the tree is 11. Now you need to do the following operations:
1)1) Multiply all weight on the path from uu to vv by xx
2)2) For all weight on the path from uu to vv, increasing xx to them
3)3) For all weight on the path from uu to vv, change them to the bitwise NOT of them
4)4) Ask the sum of the weight on the path from uu to vv
The answer modulo 2^{64}264.
Jiu Yuan is a clever girl, but she was not good at algorithm, so she hopes that you can help her solve this problem. Ding\backsim\backsim\backsim∽∽∽
The bitwise NOT is a unary operation that performs logical negation on each bit, forming the ones' complement of the given binary value. Bits that are 00 become 11, and those that are 11 become 00. For example:
NOT 0111 (decimal 7) = 1000 (decimal 8)
NOT 10101011 = 01010100
Input
The input contains multiple groups of data.
For each group of data, the first line contains a number of nn, and the number of nodes.
The second line contains (n - 1)(n−1) integers b_ibi, which means that the father node of node (i +1)(i+1) is b_ibi.
The third line contains one integer mm, which means the number of operations,
The next mm lines contain the following four operations:
At first, we input one integer opt
1)1) If opt is 11, then input 33 integers, u, v, xu,v,x, which means multiply all weight on the path from uu to vv by xx
2)2) If opt is 22, then input 33 integers, u, v, xu,v,x, which means for all weight on the path from uu to vv, increasing xx to them
3)3) If opt is 33, then input 22 integers, u, vu,v, which means for all weight on the path from uu to vv, change them to the bitwise NOT of them
4)4) If opt is 44, then input 22 integers, u, vu,v, and ask the sum of the weights on the path from uu to vv
1 \le n,m,u,v \le 10^51≤n,m,u,v≤105
1 \le x < 2^{64}1≤x<264
Output
For each operation 44, output the answer.
样例输入复制
7 1 1 1 2 2 4 5 2 5 6 1 1 1 6 2 4 5 6 3 5 2 4 2 2 2 1 4 3 1 2 4 1 2 3 1 1 4 1 1
样例输出复制
5 18446744073709551613 18446744073709551614 0
题目来源
题意:树上区间累加,区间累乘,区间按位取反,区间求和。
解题思路:赤裸裸的树链剖分+线段树维护。难点在于取反操作和取模。取反操作,其实就是二进制下 111111-X,所以就可以转换成乘 -1 + ull的最大值
然后取模……其实根本不用取模,自然溢出就是取模……学到了……比赛时还傻傻的想用bitset,所以全部运算用ull即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <algorithm>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int MAXN=200005;
ll MOD = 1000000007;
struct Edge
{
int u,v,next;
}e[MAXN];
int head[MAXN];
int edge_num;
void insert_edge(int u,int v){
e[edge_num].u=u;
e[edge_num].v=v;
e[edge_num].next=head[u];
head[u]=edge_num++;
}
int top[MAXN];
int fa[MAXN];
int deep[MAXN];
int size[MAXN];
int pos[MAXN];
int son[MAXN];
int SEG;
//求出fa,deep,num,son
void dfs1(int u,int pre,int d){
deep[u]=d;
fa[u]=pre;
size[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v!=pre){
dfs1(v,u,d+1);
size[u]+=size[v];
if(son[u]==-1||size[v]>size[son[u]])
son[u]=v;
}
}
}
//求出top和pos,求的过程中,先求重链上的dfs序
void dfs2(int u,int sp){
top[u]=sp;
pos[u]=SEG++;
if(son[u]!=-1){
dfs2(son[u],sp);
}
else{
return;
}
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v!=son[u]&&v!=fa[u]){
dfs2(v,v);
}
}
}
ll sum[MAXN<<2];
ll lazyAdd[MAXN<<2];
ll lazyMul[MAXN<<2];
int N;
void init(){
edge_num=0;
memset(head,-1,sizeof(head));
SEG=1;
memset(son,-1,sizeof(son));
}
void build(int l,int r,int rt){
lazyAdd[rt]=sum[rt]=0;
lazyMul[rt]=1;
if(l==r){
return;
}
int m=(l+r)/2;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,ll ln,ll rn){
if(lazyMul[rt]!=1){
sum[rt<<1]*=lazyMul[rt];
lazyMul[rt<<1]*=lazyMul[rt];
lazyAdd[rt<<1]*=lazyMul[rt];
sum[rt<<1|1]*=lazyMul[rt];
lazyMul[rt<<1|1]*=lazyMul[rt];
lazyAdd[rt<<1|1]*=lazyMul[rt];
lazyMul[rt]=1;
}
if(lazyAdd[rt]){
sum[rt<<1]+=lazyAdd[rt]*ln;
lazyAdd[rt<<1]+=lazyAdd[rt];
sum[rt<<1|1]+=lazyAdd[rt]*rn;
lazyAdd[rt<<1|1]+=lazyAdd[rt];
lazyAdd[rt]=0;
}
}
void updateAdd(int L,int R,ll C,int l,int r,int rt){
if(L<=l&&r<=R){
lazyAdd[rt]+=C;
sum[rt]+=C*(r-l+1);
return;
}
int m=(l+r)/2;
pushdown(rt,m-l+1,r-m);
if(L<=m)
updateAdd(L,R,C,l,m,rt<<1);
if(R>m)
updateAdd(L,R,C,m+1,r,rt<<1|1);
pushup(rt);
}
void updateMul(int L,int R,ll C,int l,int r,int rt){
if(L<=l&&r<=R){
lazyMul[rt]*=C;
lazyAdd[rt]*=C;
sum[rt]*=C;
return;
}
int m=(l+r)/2;
pushdown(rt,m-l+1,r-m);
if(L<=m)
updateMul(L,R,C,l,m,rt<<1);
if(R>m)
updateMul(L,R,C,m+1,r,rt<<1|1);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return sum[rt];
}
int m=(l+r)/2;
pushdown(rt,m-l+1,r-m);
ll ans=0;
if(L<=m)
ans+=query(L,R,l,m,rt<<1);
if(R>m)
ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
pushup(rt);
}
void updateAdd(int u,int v,ll C){
int f1=top[u];
int f2=top[v];
while(f1!=f2){
if(deep[f1]<deep[f2]){
swap(f1,f2);
swap(u,v);
}
updateAdd(pos[f1],pos[u],C,1,N,1);
u=fa[f1];
f1=top[u];
}
if(deep[u]>deep[v])
swap(u,v);
updateAdd(pos[u],pos[v],C,1,N,1);
}
void updateMul(int u,int v,ll C){
int f1=top[u];
int f2=top[v];
while(f1!=f2){
if(deep[f1]<deep[f2]){
swap(f1,f2);
swap(u,v);
}
updateMul(pos[f1],pos[u],C,1,N,1);
u=fa[f1];
f1=top[u];
}
if(deep[u]>deep[v])
swap(u,v);
updateMul(pos[u],pos[v],C,1,N,1);
}
ll query(int u,int v){
int f1=top[u];
int f2=top[v];
ll temp=0;
while(f1!=f2){
if(deep[f1]<deep[f2]){
swap(f1,f2);
swap(u,v);
}
temp+=query(pos[f1],pos[u],1,N,1);
u=fa[f1];
f1=top[u];
}
if(deep[u]>deep[v])
swap(u,v);
return temp+query(pos[u],pos[v],1,N,1);
}
int main(){
ll FONE=18446744073709551615;
while(~scanf("%d",&N)){
int tmp;
init();
for(int i=2;i<=N;i++){
scanf("%d",&tmp);
insert_edge(i,tmp);
insert_edge(tmp,i);
}
dfs1(1,0,0);
dfs2(1,1);
build(1,N,1);
int Q;
scanf("%d",&Q);
int op,u,v;
ll x;
while(Q--){
scanf("%d",&op);
if(op==1){
scanf("%d%d%llu",&u,&v,&x);
updateMul(u,v,x);
}
if(op==2){
scanf("%d%d%llu",&u,&v,&x);
updateAdd(u,v,x);
}
if(op==3){
scanf("%d%d",&u,&v);
updateMul(u,v,-1);
updateAdd(u,v,FONE);
}
if(op==4){
scanf("%d%d",&u,&v);
printf("%llu\n",query(u,v));
}
}
}
return 0;
}