【GDOI 2016 Day1】疯狂动物城

原创 2016年06月01日 19:28:32

题目

这里写图片描述

分析

注意注意:码农题一道,打之前做好心理准备。
对于操作1、2,修改或查询xy的路径,显然树链剖分
对于操作2,我们将xy的路径分为xlca(x,y)lca(x,y)y两部分。
对于第一部分的某个点i,设它到y的距离为s,那么s=deep[i]+deep[y]-2*deep[lca(x,y)]i对答案的贡献为a[i]s(s+1)/2,如果不考虑除以2,设t=deep[y]-2*deep[lca(x,y)],则贡献为a[i]deep[i]^2+a[i]*deep[i](2*t+1)+a[i]*(t+t^2)
对于第二部分的点i,s=deep[y]-deep[i],设lca(x,y),则贡献为a[i]deep[i]^2-a[i]*deep[i](2*t+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;
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【GDOI 2016 Day1】第四题 疯狂动物城 题解+代码

我恨码农题!!!题目大意一棵树,三个操作 1、从X到Y的路径上每个点的权值加Z 2、查询X到Y的一些神奇东西 3、将树回复到第X次操作后的状态输入第一行n,m。n个点,m个操作 接下来n-1行...

GDOI 2016 Day1 T4 疯狂动物城

Description给出一个N个节点的数,和M次操作。每次操作的类型如下: 1,x,y,z,将x到y的路径上的ai加上z 2,x,y,询问x到y的路径上,ai*(1+2+..+n-i)的和 3...

【GDOI 2016 Day1】第四题 疯狂动物城

Description题目自己脑补 抽象题意:求可持久化树链剖分 solution一道巨型码农题! 对于每个数,我们要求aj∗i∗(i+1)/2a_j*i*(i+1)/2, 拆一下:aj∗(i...
  • HOWARLI
  • HOWARLI
  • 2016年05月17日 19:13
  • 585

【GDOI 2016】第四题 疯狂动物城

DescriptionSolution题目好长,一看就烦操作1:1,x,y,z把x到y的点权值加z。 操作2:2,x,y把x到y的点一次放进一个数组a里面,统计答案ans=∑ni=1a[i]∗∑n−...

GDOI 2016 Day1 第一题 中学生数学题 解题报告

题目大意给出三个数n0n_0(n0n_0>0且为整数)、p0p_0和kk。 第一问: 满足nn=⌊n0−kp⌋\lfloor n_0-kp \rfloor,问nn*(pp-p0p_0)的最大值。...

【GDOI 2016 Day1】第一题 中学生数学题

Description给定商品成本 p0 和系数 k ,常数 n0 ,设价格为 p ,购买商品人数满足n1 =⌊\lfloor n0 -k*p⌋\rfloor 其中 p , k 为实数, 0 n 为整...

GDOI 2016 Day2 T1 SigemaGO

Description给出一张n个点,m条边的有向图。若A->B有一条边,B->C有一条边,则可以使用L的时间直接从A到C。总共只可以走lim次这样的近路。求1到n的最短路。若无解,输出-1。 n...

JZOJ 4485【GDOI 2016 Day1】第一题 中学生数学题

Description 给定商品成本 p0 和系数 k ,常数 n0 ,设价格为 p ,购买商品人数满足n1=⌊n0−k∗p⌋n1 =⌊ n0 -k*p⌋ 其中 p , k 为实数, n0 为整数。 ...

【JZOJ 4486】【GDOI 2016 Day1】第二题 最长公共子串

Description给你两个字符串S,T 给你N个区间,S串中这些区间内的字符可以随意改变在区间中的位置。 求S,T可以达到的的最长公共子串长度。Analysis可以用双指针移动,我打的是d...

GDOI 2016 Day1 T2 最长公共子串

Description给出两个字符串A和B,求最长公共子串。 其中B串中有k个区间的字符可以任意调换。 |A|,|B|...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【GDOI 2016 Day1】疯狂动物城
举报原因:
原因补充:

(最多只允许输入30个字)