【GDOI 2016 Day1】疯狂动物城

题目

这里写图片描述

分析

注意注意:码农题一道,打之前做好心理准备。
对于操作1、2,修改或查询xy的路径,显然树链剖分
对于操作2,我们将xy的路径分为xlca(x,y)lca(x,y)y两部分。
对于第一部分的某个点i,设它到y的距离为s,那么s=deep[i]+deep[y]-2deep[lca(x,y)]i对答案的贡献为a[i]s(s+1)/2,如果不考虑除以2,设t=deep[y]-2deep[lca(x,y)],则贡献为a[i]deep[i]^2+a[i]deep[i](2t+1)+a[i](t+t^2)
对于第二部分的点i,
s=deep[y]-deep[i],设lca(x,y),则贡献为a[i]
deep[i]^2-a[i]deep[i](2t+1)+a[i](t+t^2)

接着,对于每个点i我们就用线段树来维护a[i]deep[i]^2a[i]deep[i]以及a[i]
注意:最后记得除2,由于mod 20160501,用逆元。还有,lca(x,y)的贡献会重复,要减掉重复的。
对于操作3,打个可持久化线段树。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=20160501;
using namespace std;
struct trees
{
    long long lazy,l,r;
    long long v1;//a[i]*deep[i]^2
    long long v2;//a[i]*deep[i]
    long long v3;//a[i]
    long long d;
    long long d2;
    
}tree[7000000];
long long g[200005][25],d[200005],son[200005],deep[200005],size[200005],fa[200005],top[200005],bef[200005],f[220005];
long long last[200005],next[200005],to[200005];
long long n,m,ans,t,po,tot,tt;
long long bj(long long x,long long y)
{
    next[++tot]=last[x];
    last[x]=tot;
    to[tot]=y;
}
long long premi()
{
    for(long long j=1;j<=log2(n);j++)
    {
        for(long long i=1;i<=n;i++)
        {
            g[i][j]=g[g[i][j-1]][j-1];
        }
    }
}
long long build(long long x)
{
    size[x]=1;
    g[x][0]=fa[x];
    long long mx=0;
    for(long long i=last[x];i;i=next[i])
    {
        long long j=to[i];
        if(j!=fa[x])
        {
            fa[j]=x;
            deep[j]=deep[x]+1;
            build(j);
            size[x]+=size[j];
            if(size[j]>mx)
            {
                mx=size[j];
                son[x]=j;
            }
        }
    }
}
long long build1(long long x)
{
    d[++tot]=x;
    bef[x]=tot;
    if(!top[x])
    {
        top[x]=x;
    }
    if(son[x])
    {
        top[son[x]]=top[x];
        build1(son[x]);
    }
    for(long long i=last[x];i;i=next[i])
    {
        long long j=to[i];
        if(j!=fa[x] && son[x]!=j)
        {
            build1(j);
        }
    }
}
long long bnew(long long v,long long l,long long r,long long e)
{
    if(l==r)
    {
        tree[v].lazy=0;
        return 0;
    }
    long long mid=(l+r)/2;
    if(e!=2)
    {
        tree[++tot]=tree[tree[v].l];
        if(e==3)
        {
            tree[tot].v1=(tree[tot].v1+tree[v].lazy*tree[tot].d2)%mo;
            tree[tot].v2=(tree[tot].v2+tree[v].lazy*tree[tot].d)%mo;
            tree[tot].v3=(tree[tot].v3+tree[v].lazy*(mid-l+1))%mo;
            tree[tot].lazy=(tree[tot].lazy+tree[v].lazy)%mo;
        }
        tree[v].l=tot;
    }
    if(e>=2)
    {
        tree[++tot]=tree[tree[v].r];
        if(e==3)
        {
            tree[tot].v1=(tree[tot].v1+tree[v].lazy*tree[tot].d2)%mo;
            tree[tot].v2=(tree[tot].v2+tree[v].lazy*tree[tot].d)%mo;
            tree[tot].v3=(tree[tot].v3+tree[v].lazy*(r-(mid+1)+1))%mo;
            tree[tot].lazy=(tree[tot].lazy+tree[v].lazy)%mo;
        }
        tree[v].r=tot;
    }
    tree[v].lazy=0;
}
long long change1(long long v,long long l,long long r,long long x,long long value)
{
    if(l==r)
    {
        tree[v].v3=value;
        tree[v].v2=value*deep[d[l]];
        tree[v].v1=value*deep[d[l]]*deep[d[l]];
        tree[v].d=deep[d[l]];
        tree[v].d2=deep[d[l]]*deep[d[l]];
        return 0;
    }
    long long mid=(l+r)/2;
    if(x<=mid)
    {
        if(!tree[v].l) tree[v].l=++tot;
        change1(tree[v].l,l,mid,x,value);
    }
    else
    {
        if(!tree[v].r) tree[v].r=++tot;
        change1(tree[v].r,mid+1,r,x,value);
    }
    tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
    tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
    tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
    tree[v].d=tree[tree[v].l].d+tree[tree[v].r].d;
    tree[v].d2=tree[tree[v].l].d2+tree[tree[v].r].d2;
}
long long change(long long v,long long l,long long r,long long x,long long y,long long value)
{
    if(l==x && r==y)
    {
        tree[v].v1=tree[v].v1+value*tree[v].d2;
        tree[v].v2=tree[v].v2+value*tree[v].d;
        tree[v].v3=tree[v].v3+value*(r-l+1);
        tree[v].lazy=tree[v].lazy+value;
        return 0;
    }
    bool bz=true;
    if(tree[v].lazy)
    {
        bnew(v,l,r,3);
        bz=false;
    }
    long long mid=(l+r)/2;
    if(y<=mid)
    {
        
        if(bz) bnew(v,l,r,1);
        change(tree[v].l,l,mid,x,y,value);
    }
    else
    if(x>=mid+1)
    {
        if(bz) bnew(v,l,r,2);
        change(tree[v].r,mid+1,r,x,y,value);
    }
    else
    {
        if(bz) bnew(v,l,r,4);
        change(tree[v].l,l,mid,x,mid,value);
        change(tree[v].r,mid+1,r,mid+1,y,value);
    }
    tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
    tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
    tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
}
long long lca(long long x,long long y)
{
    if(deep[x]>deep[y])
    {
        x=x^y;
        y=x^y;
        x=x^y;
    }
    for(long long i=log2(n);i>=0;i--)
    {
        if(deep[g[y][i]]>deep[x])
            y=g[y][i];
    }
    if(deep[y]!=deep[x]) y=g[y][0];
    for(long long i=log2(n);i>=0;i--)
    {
        if(g[y][i]!=g[x][i])
        {
            y=g[y][i];
            x=g[x][i];
        }
    }
    if(x!=y) y=g[y][0];
    return y;
}
long long find(long long v,long long l,long long r,long long x,long long y,long long value,long long o)
{
    if(l==x && r==y)
    {
        return ((tree[v].v1+o*tree[v].v2*(2*value+1)+tree[v].v3*(value+value*value))%mo+mo)%mo;
    }
    if(tree[v].lazy)
    {
        bnew(v,l,r,3);
    }
    long long mid=(l+r)/2,e=0;
    if(y<=mid)
    {
        e=find(tree[v].l,l,mid,x,y,value,o);
    }
    else
    if(x>=mid+1)
    {
        e=find(tree[v].r,mid+1,r,x,y,value,o);
    }
    else
    {
        e=find(tree[v].l,l,mid,x,mid,value,o)+find(tree[v].r,mid+1,r,mid+1,y,value,o);
    }
    tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
    tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
    tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
    return e;
} 
long long work(long long x,long long y,long long z)
{
    if(z)
    {
        f[++t]=++tot;
        tree[tot]=tree[f[tt]];
        tt=t;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]>=deep[top[y]])
            {
                change(f[t],1,n,bef[top[x]],bef[x],z);
                x=fa[top[x]];
            }
            else
            {
                change(f[t],1,n,bef[top[y]],bef[y],z);
                y=fa[top[y]];
            }
        }
        if(deep[x]>=deep[y])
        {
            change(f[t],1,n,bef[y],bef[x],z);
        }
        else
        {
            change(f[t],1,n,bef[x],bef[y],z);
        }
    }
    else
    {
        ans=0;
        long long lc=lca(x,y),xx=x,yy=y;
        long long p=deep[yy]-deep[lc]*2;
        x=xx;
        y=lc;
        if(x!=y)
        {
            while(top[x]!=top[y])
            {
                if(deep[top[x]]>=deep[top[y]])
                {
                    ans=((ans+find(f[tt],1,n,bef[top[x]],bef[x],p,1))%mo+mo)%mo;
                    x=fa[top[x]];
                }
                else
                {
                    ans=((ans+find(f[tt],1,n,bef[top[y]],bef[y],p,1))%mo+mo)%mo;
                    y=fa[top[y]];
                }
            }
            if(deep[x]>=deep[y])
            {
                ans=((ans+find(f[tt],1,n,bef[y],bef[x],p,1))%mo+mo)%mo;
            }
            else
            {
                ans=((ans+find(f[tt],1,n,bef[x],bef[y],p,1))%mo+mo)%mo;
            }
            if(lc!=yy) ans=((ans-find(f[tt],1,n,bef[lc],bef[lc],p,1))%mo+mo)%mo;
        }
        x=lc;
        y=yy;
        p=deep[yy];
        if(x!=y)
        {
            while(top[x]!=top[y])
            {
                if(deep[top[x]]>=deep[top[y]])
                {
                    ans=((ans+find(f[tt],1,n,bef[top[x]],bef[x],p,-1))%mo+mo)%mo;
                    x=fa[top[x]];
                }
                else
                {
                    ans=((ans+find(f[tt],1,n,bef[top[y]],bef[y],p,-1))%mo+mo)%mo;
                    y=fa[top[y]];
                }
            }
            if(deep[x]>=deep[y])
            {
                ans=((ans+find(f[tt],1,n,bef[y],bef[x],p,-1))%mo+mo)%mo;
            }
            else
            {
                ans=((ans+find(f[tt],1,n,bef[x],bef[y],p,-1))%mo+mo)%mo;
            }
        }
        ans=(ans%mo+mo)*10080251%mo;
        printf("%lld\n",ans);
    }
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=n-1;i++)
    {
        long long x,y;
        scanf("%lld%lld",&x,&y);
        bj(x,y);
        bj(y,x);
    }
    tot=0;
    deep[1]=1;
    build(1);
    build1(1);
    tot=1;
    f[0]=1;
    t=0;
    tt=0;
    for(long long i=1;i<=n;i++)
    {
        long long x;
        scanf("%lld",&x);
        change1(1,1,n,bef[i],x);
    }
    premi();
    ans=0;
    for(long long i=1;i<=m;i++)
    {
        long long p,x,y,z;
        scanf("%lld",&p);
        if(p==1)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            work(x^ans,y^ans,z);
        }
        else
        if(p==2)
        {
            scanf("%lld%lld",&x,&y);
            work(x^ans,y^ans,0);
        }
        else
        {
            scanf("%lld",&x);
            tt=x^ans;
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9029674.html
今日推荐