动物园 - 树剖 - 主席树

给你一棵树,支持链加,和给定一条路径x-y,假设从y走到x的权值序列是{a},求
i a i i 2 i a i i 2 ,还有返回到之前某个版本。
题解:直接树剖然后可持久化掉线段树即可,维护区间 i i k a i , k 2 即可。

#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;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82025554