题面:
有一棵根节点为1的树,初始时节点权值均为0
可执行的操作:
x到y路径上的节点权值全部乘以一个数z
x到y路径上的节点权值全部加上一个数z
x到y路径上的节点权值全部取反
查询x到y路径上的节点权值和。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
namespace onlyzhao
{
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define forhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define one(n) for(int i=1;i<=(n);i++)
#define rone(n) for(int i=(n);i>=1;i--)
#define fone(i,x,n) for(int i=(x);i<=(n);i++)
#define frone(i,n,x) for(int i=(n);i>=(x);i--)
#define fonk(i,x,n,k) for(int i=(x);i<=(n);i+=(k))
#define fronk(i,n,x,k) for(int i=(n);i>=(x);i-=(k))
#define two(n,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define ftwo(i,n,j,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define cls(a) memset(a,0,sizeof(a))
#define cls1(a) memset(a,-1,sizeof(a))
#define clsmax(a) memset(a,0x3f,sizeof(a))
#define clsmin(a) memset(a,0x80,sizeof(a))
#define cln(a,num) memset(a,0,sizeof(a[0])*num)
#define cln1(a,num) memset(a,-1,sizeof(a[0])*num)
#define clnmax(a,num) memset(a,0x3f,sizeof(a[0])*num)
#define clnmin(a,num) memset(a,0x80,sizeof(a[0])*num)
#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scl(x) scanf("%lld",&x)
#define scl2(x,y) scanf("%lld%lld",&x,&y)
#define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scf(x) scanf("%lf",&x)
#define scf2(x,y) scanf("%lf%lf",&x,&y)
#define scf3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scs(x) scanf("%s",x+1)
#define scs0(x) scanf("%s",x)
#define scline(x) scanf("%[^\n]%*c",x+1)
#define scline0(x) scanf("%[^\n]%*c",x)
#define pcc(x) putchar(x)
#define pc(x) printf("%d\n",x)
#define pc2(x,y) printf("%d %d\n",x,y)
#define pc3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pck(x) printf("%d ",x)
#define pcl(x) printf("%lld\n",x)
#define pcl2(x,y) printf("%lld %lld\n",x,y)
#define pcl3(x,y,z) printf("%lld %lld %d\n",x,y,z)
#define pclk(x) printf("%lld ",x)
#define pcf2(x) printf("%.2f\n",x)
#define pcf6(x) printf("%.6f\n",x)
#define pcf8(x) printf("%.8f\n",x)
#define pcs(x) printf("%s\n",x+1)
#define pcs0(x) printf("%s\n",x)
#define pcline(x) printf("%d**********\n",x)
char buffer[100001],*S,*T;
inline char Get_Char()
{
if (S==T)
{
T=(S=buffer)+fread(buffer,1,100001,stdin);
if (S==T) return EOF;
}
return *S++;
}
inline int read()
{
char c;int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
return re;
}
};
using namespace onlyzhao;
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int maxm=100100;
const int up=100000;
const int hp=13331;
const int maxn=100100;
//取反x -> (2^64-1)- x
//即 x * -1 + (2^64-1)
//其中 -1 == 2^64-1
const llu p=-1ll;
int n,m,r,k;
int head[maxn],ver[maxn],nt[maxn];
int f[maxn],d[maxn],si[maxn],son[maxn],rk[maxn];
int top[maxn],id[maxn];
int tot=1,cnt=0;
void init(void)
{
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
tot=1,cnt=0;
}
void add(int x,int y)
{
ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}
void dfs1(int x,int fa)
{
int max_son=0;
si[x]=1;
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa) continue;
f[y]=x;
d[y]=d[x]+1;
dfs1(y,x);
si[x]+=si[y];
if(si[y]>max_son)max_son=si[y],son[x]=y;
}
}
void dfs2(int x,int t)
{
top[x]=t;
id[x]=++cnt;
rk[cnt]=x;
if(!son[x]) return ;
dfs2(son[x],t);
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y!=son[x]&&y!=f[x])
dfs2(y,y);
}
}
struct node
{
int l,r;
llu sum;
llu mul;
llu add;
}t[maxn<<2];
void pushup(int cnt)
{
t[cnt].sum=t[lc].sum+t[rc].sum;
}
void pushdown(int cnt)
{
if(t[cnt].mul==1&&t[cnt].add==0) return ;
t[lc].sum=t[lc].sum*t[cnt].mul+t[cnt].add*len(lc);
t[rc].sum=t[rc].sum*t[cnt].mul+t[cnt].add*len(rc);
t[lc].mul=t[lc].mul*t[cnt].mul;
t[rc].mul=t[rc].mul*t[cnt].mul;
t[lc].add=t[lc].add*t[cnt].mul+t[cnt].add;
t[rc].add=t[rc].add*t[cnt].mul+t[cnt].add;
t[cnt].add=0;
t[cnt].mul=1;
return ;
}
void build(int l,int r,int cnt)
{
t[cnt].add=0;t[cnt].mul=1;
t[cnt].l=l;t[cnt].r=r;
if(l==r)
{
t[cnt].sum=0;
return ;
}
int mid=(l+r)/2;
build(l,mid,cnt<<1);
build(mid+1,r,cnt<<1|1);
pushup(cnt);
return ;
}
void change(int l,int r,int cnt,ll val,int flag)
{
if(l<=t[cnt].l&&t[cnt].r<=r)
{
if(flag)
{
t[cnt].sum=t[cnt].sum+len(cnt)*val;
t[cnt].add=t[cnt].add+val;
}
else
{
t[cnt].sum=t[cnt].sum*val;
t[cnt].add=t[cnt].add*val;
t[cnt].mul=t[cnt].mul*val;
}
return ;
}
pushdown(cnt);
if(l<=t[cnt<<1].r) change(l,r,cnt<<1,val,flag);
if(r>=t[cnt<<1|1].l) change(l,r,cnt<<1|1,val,flag);
pushup(cnt);
return ;
}
llu ask(int l,int r,int cnt)
{
if(l<=t[cnt].l&&t[cnt].r<=r)
return t[cnt].sum;
llu ans=0;
pushdown(cnt);
if(l<=t[cnt<<1].r) ans=ans+ask(l,r,cnt<<1);
if(r>=t[cnt<<1|1].l) ans=ans+ask(l,r,cnt<<1|1);
return ans;
}
void change_road(int x,int y,llu val,int flag)
{
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])
swap(x,y);
change(id[top[x]],id[x],1,val,flag);
x=f[top[x]];
}
if(id[x]>id[y]) swap(x,y);
change(id[x],id[y],1,val,flag);
}
llu ask_road(int x,int y)
{
llu ans=0;
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])
swap(x,y);
ans=ans+ask(id[top[x]],id[x],1);
x=f[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans=ans+ask(id[x],id[y],1);
return ans;
}
int main(void)
{
while(scanf("%d",&n)!=EOF)
{
init();
int pos,x,y;
llu val;
for(int i=2;i<=n;i++)
{
scanf("%d",&x);
add(x,i);
}
dfs1(1,0);
dfs2(1,1);
build(1,cnt,1);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&pos);
if(pos==1)
{
scanf("%d%d%llu",&x,&y,&val);
change_road(x,y,val,0);
}
else if(pos==2)
{
scanf("%d%d%llu",&x,&y,&val);
change_road(x,y,val,1);
}
else if(pos==3)
{
scanf("%d%d",&x,&y);
change_road(x,y,p,0);
change_road(x,y,p,1);
}
else
{
scanf("%d%d",&x,&y);
printf("%llu\n",ask_road(x,y));
}
}
}
return 0;
}