区间更新加法与乘法,x取反是2^64-x-1,由于取模所以取反变成-x-1,就区间*-1再-1就可以了,最后区间询问求和。
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define LMissher using namespace std; typedef long long ll; typedef unsigned long long ull; typedef double db; const int M = 1e5+7; const double pi = acos(-1); const int inf = 2147483647; const int mod = 1e9+7; int n,q; int tot,cnt,head[M]; int sz[M],f[M],son[M],dep[M],rnk[M],id[M],top[M]; struct edge { int v,nex; }e[M<<1]; void init(){ tot=cnt=0;mem1(head); } void add(int u,int v){ e[++cnt].v=v;e[cnt].nex=head[u]; head[u]=cnt; } void dfs(int u,int fa,int d){ sz[u]=1,f[u]=fa,dep[u]=d,son[u]=-1; for(int i=head[u];~i;i=e[i].nex){ int v=e[i].v; if(v==fa) continue; dfs(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1||sz[son[u]]<sz[v]) son[u]=v; } return ; } void dfs1(int u,int t){ id[u]=++tot; rnk[tot]=u; top[u]=t; if(son[u]==-1) return ; dfs1(son[u],t); for(int i=head[u];~i;i=e[i].nex){ int v=e[i].v; if(v==f[u]||v==son[u]) continue; dfs1(v,v); } return ; } struct Seg { ull sum[M<<2],lazy[M<<2],lazy1[M<<2],len[M<<2]; void pushup(int rt,int l,int r){ sum[rt]=sum[l]+sum[r]; } void pushdown(int rt,int l,int r){ if(lazy1[rt]!=1ull){ ull v=lazy1[rt]; lazy1[rt]=1ull; lazy1[l]*=v;lazy1[r]*=v; lazy[l]*=v;lazy[r]*=v; sum[l]*=v;sum[r]*=v; } if(lazy[rt]){ ull v=lazy[rt]; lazy[rt]=0ull; lazy[l]+=v;lazy[r]+=v; sum[l]+=(v*len[l]);sum[r]+=(v*len[r]); } } void build(int l,int r,int rt){ len[rt]=(ull)(r-l+1ull);sum[rt]=0ull; lazy1[rt]=1ull;lazy[rt]=0ull; if(l==r) return ; int mid=(l+r)>>1; build(lson); build(rson); pushup(up); } void updateadd(int L,int R,int l,int r,int rt,ull v){ if(L<=l&&r<=R){ sum[rt]+=(v*len[rt]); lazy[rt]+=v; return ; } pushdown(up); int mid=(l+r)>>1; if(L<=mid) updateadd(L,R,lson,v); if(R>mid) updateadd(L,R,rson,v); pushup(up); } void updatemul(int L,int R,int l,int r,int rt,ull v){ if(L<=l&&r<=R){ sum[rt]*=v; lazy[rt]*=v; lazy1[rt]*=v; return ; } pushdown(up); int mid=(l+r)>>1; if(L<=mid) updatemul(L,R,lson,v); if(R>mid) updatemul(L,R,rson,v); pushup(up); } ull query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]; } pushdown(up); int mid=(l+r)>>1;ull res=0ull; if(L<=mid) res+=query(L,R,lson); if(R>mid) res+=query(L,R,rson); return res; } }seg; void update(int x,int y,int op,ull v){ int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]>dep[fy]){ if(op==2) seg.updateadd(id[fx],id[x],1,n,1,v); else seg.updatemul(id[fx],id[x],1,n,1,v); x=f[fx];fx=top[x]; } else{ if(op==2) seg.updateadd(id[fy],id[y],1,n,1,v); else seg.updatemul(id[fy],id[y],1,n,1,v); y=f[fy];fy=top[y]; } } if(dep[x]>dep[y]){ if(op==2) seg.updateadd(id[y],id[x],1,n,1,v); else seg.updatemul(id[y],id[x],1,n,1,v); } else{ if(op==2) seg.updateadd(id[x],id[y],1,n,1,v); else seg.updatemul(id[x],id[y],1,n,1,v); } } ull query(int x,int y){ int fx=top[x],fy=top[y];ull res=0; while(fx!=fy){ if(dep[fx]>dep[fy]){ res+=seg.query(id[fx],id[x],1,n,1); x=f[fx],fx=top[x]; } else{ res+=seg.query(id[fy],id[y],1,n,1); y=f[fy],fy=top[y]; } } if(dep[x]>dep[y]) res+=seg.query(id[y],id[x],1,n,1); else res+=seg.query(id[x],id[y],1,n,1); return res; } int main(){ #ifdef LMissher freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif while(~scanf("%d",&n)){ seg.build(1,n,1); init(); for(int i=2;i<=n;i++){ int far; scanf("%d",&far); add(far,i);add(i,far); } dfs(1,-1,0); dfs1(1,1); scanf("%d",&q); int opt,u,v;ull val; while(q--){ scanf("%d",&opt); if(opt==1||opt==2){ scanf("%d%d%llu",&u,&v,&val); update(u,v,opt,val); } if(opt==3){ scanf("%d%d",&u,&v); update(u,v,1,-1ull); update(u,v,2,-1ull); } if(opt==4){ scanf("%d%d",&u,&v); printf("%llu\n",query(u,v)); } } } return 0; }