给你一棵树,支持链加,和给定一条路径x-y,假设从y走到x的权值序列是{a},求
,还有返回到之前某个版本。
题解:直接树剖然后可持久化掉线段树即可,维护区间
即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define lint long long
#define mod 20160501
#define N 100010
#define M 100010
#define inv2 10080251ll
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,in[N],fa[N],dfs_clock,d[N],tms[N];
int ecxs[N],scxs[N],a[N],lst[N],top[N],sz[N],son[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int fir_dfs(int x,int f=0)
{
fa[x]=f,d[x]=d[f]+1;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa[x])
{
sz[x]+=fir_dfs(y,x);
if(sz[son[x]]<sz[y]) son[x]=y;
}
return ++sz[x];
}
int sec_dfs(int x)
{
tms[in[x]=++dfs_clock]=x;
if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]);
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)!=son[x]&&e[i].to!=fa[x])
top[y]=y,sec_dfs(y);
return 0;
}
struct node{
int c,s0,s1,s2;
node(int d=0,int a=0,int b=0,int _c=0) { c=d,s0=a,s1=b,s2=_c; }
inline int init(int _c=0,int x=0) { return c=_c,s0=s1=s2=x; }
inline node operator=(const node &n)
{ return c=n.c,s0=n.s0,s1=n.s1,s2=n.s2,*this; }
inline node operator+(const node &n)const
{
static node r;r.c=c+n.c;
r.s0=s0+n.s0,(r.s0>=mod?r.s0-=mod:0);
r.s1=(s1+n.s1+(lint)c*n.s0)%mod;
r.s2=(s2+n.s2+2ll*c*n.s1+(lint)c*c*n.s0)%mod;
return r;
}
inline node operator+(int v)const
{
static node r;r.c=c;
r.s0=(s0+(lint)c*v)%mod;
r.s1=(s1+(lint)ecxs[c]*v)%mod;
r.s2=(s2+(lint)scxs[c]*v)%mod;
return r;
}
inline node operator+=(int v)
{ return (*this)=(*this)+v; }
inline node operator+=(const node &n)
{ return (*this)=(*this)+n; }
inline int show()
{ return debug(c)sp,debug(s0)sp,debug(s1)sp,debug(s2)ln,0; }
};
struct segment{
int l,r,pt;
node ltr,rtl;
segment *ch[2];
}*T[M];
inline int push_up(segment* &rt)
{
rt->ltr=(rt->ch[0]->ltr+rt->ch[0]->pt)+(rt->ch[1]->ltr+rt->ch[1]->pt),
rt->rtl=(rt->ch[1]->rtl+rt->ch[1]->pt)+(rt->ch[0]->rtl+rt->ch[0]->pt);
return 0;
}
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r,rt->pt=0;int mid=(l+r)>>1;
if(l==r) return rt->ltr.init(1,a[tms[l]]),rt->rtl.init(1,a[tms[r]]),0;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r),push_up(rt);
}
int update(segment* &p,segment* &n,int s,int t,int v)
{
n=new segment,n->l=p->l,n->r=p->r,
n->ltr=p->ltr,n->rtl=p->rtl,n->pt=p->pt,
n->ch[0]=p->ch[0],n->ch[1]=p->ch[1];
int l=n->l,r=n->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return (n->pt+=v)%=mod;
if(s<=mid) update(p->ch[0],n->ch[0],s,t,v);
if(mid<t) update(p->ch[1],n->ch[1],s,t,v);
return push_up(n);
}
node query(segment* &rt,int s,int t,int ltr,int v=0)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;(v+=rt->pt)%=mod;
if(s<=l&&r<=t) return ltr?rt->ltr+v:(rt->rtl+v);
if(t<=mid) return query(rt->ch[0],s,t,ltr,v);
if(mid<s) return query(rt->ch[1],s,t,ltr,v);
if(ltr) return query(rt->ch[0],s,t,ltr,v)+query(rt->ch[1],s,t,ltr,v);
return query(rt->ch[1],s,t,ltr,v)+query(rt->ch[0],s,t,ltr,v);
}
inline int update(int x,int y,int v,segment* &pre,segment* &now)
{
static segment *tmp;tmp=now=pre;
for(;top[x]^top[y];x=fa[top[x]])
{
if(d[top[x]]<d[top[y]]) swap(x,y);
update(tmp,now,in[top[x]],in[x],v),tmp=now;
}
if(d[x]<d[y]) swap(x,y);
return update(tmp,now,in[y],in[x],v),0;
}
inline int Query(segment* &rt,int x,int y,int c=0)
{
static node ans;ans.init(0,0);
while(top[x]!=top[y])
if(d[top[x]]>=d[top[y]]) ans+=query(rt,in[top[x]],in[x],0),x=fa[top[x]];
else lst[++c]=y,y=fa[top[y]];
if(d[x]>d[y]) ans+=query(rt,in[y],in[x],0);
else ans+=query(rt,in[x],in[y],1);
for(int i=c;i;i--) y=lst[i],ans+=query(rt,in[top[y]],in[y],1);
return (ans.s2-ans.s1+mod)*inv2%mod;
}
int main()
{
int n=inn(),m=inn(),cnt=0,cur=0,las=0;
for(int i=1,u,v;i<n;i++)
u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
for(int i=1;i<=n;i++) a[i]=inn();
for(int i=1;i<=n;i++)
ecxs[i]=i*(i+1ll)/2%mod,
scxs[i]=i*(i+1ll)*(2*i+1)/6%mod;
fir_dfs(1),top[1]=1,sec_dfs(1),build(T[0],1,n);
while(m--)
{
int opt=inn(),x,y,dlt;
if(opt==1) x=inn()^las,y=inn()^las,dlt=inn(),update(x,y,dlt,T[cur],T[++cnt]),cur=cnt;
else if(opt==2) x=inn()^las,y=inn()^las,printf("%d\n",las=Query(T[cur],y,x)%mod);
else cur=inn()^las;
}
return 0;
}