bzoj3730 震波

Posted liguanlin1124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3730 震波相关的知识,希望对你有一定的参考价值。

题目描述

题解:

好像和皮皮鼠那题一模一样。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100050
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){c=10*c+ch-0;ch=getchar();}
    return f*c;
}
int n,m,v[N],hed[N],cnt;
struct EG
{
    int to,nxt;
}e[2*N];
void ae(int f,int t)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
int dep[N],fa[N],son[N],siz[N],top[N];
void dfs1(int u,int f)
{
    fa[u] = f;
    siz[u] = 1;
    dep[u] = dep[f]+1;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to==f)continue;
        dfs1(to,u);
        siz[u]+=siz[to];
        if(siz[to]>siz[son[u]])son[u] = to;
    }
}
void dfs2(int u,int tp)
{
    top[u] = tp;
    if(!son[u])return ;
    dfs2(son[u],tp);
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to==fa[u]||to==son[u])continue;
        dfs2(to,to);
    }
}
int get_lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])std::swap(x,y);
        x = fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y)
{
    return dep[x]+dep[y]-2*dep[get_lca(x,y)];
}
int rt,sum,w[N],sz[N],uf[N],mrk[N];
void get_rt(int u,int f)
{
    sz[u]=1,w[u]=0;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(mrk[to]||to==f)continue;
        get_rt(to,u);
        sz[u]+=sz[to];
        if(sz[to]>w[u])w[u]=sz[to];
    }
    if(sum-sz[u]>w[u])w[u]=sum-sz[u];
    if(w[u]<w[rt])rt=u;
}
void work(int u)
{
    mrk[u] = 1;int pre = sum;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(mrk[to])continue;
        rt = 0,sum = (sz[to]>sz[u]?pre-sz[u]:sz[to]);
        get_rt(to,0);uf[rt] = u;
        work(rt);
    }
}
struct segtree
{
    int tot,rt[N],ls[N*80],rs[N*80],vl[N*80];
    void insert(int l,int r,int &u,int qx,int d)
    {
        if(!u)u = ++tot;
        vl[u]+=d;
        if(l==r)return ;
        int mid = (l+r)>>1;
        if(qx<=mid)insert(l,mid,ls[u],qx,d);
        else insert(mid+1,r,rs[u],qx,d);
    }
    int query(int l,int r,int u,int qr)
    {
        if(!u)return 0;
        if(r==qr)return vl[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,ls[u],qr);
        else return vl[ls[u]]+query(mid+1,r,rs[u],qr);
    }
    void push(int x,int qx,int d)
    {
        qx = qx<n?qx:n;
        insert(0,n,rt[x],qx,d);
    }
    int ask(int x,int lim)
    {
        return query(0,n,rt[x],lim);
    }
}tr1,tr2;
int main()
{
    n = rd(),m = rd();
    for(int i=1;i<=n;i++)v[i] = rd();
    for(int f,t,i=1;i<n;i++)
    {
        f = rd(),t = rd();
        ae(f,t),ae(t,f);
    }
    dfs1(1,0),dfs2(1,1);
    w[0]=0x3f3f3f3f,rt=0,sum=n;
    get_rt(1,0);work(rt);
    for(int i=1;i<=n;i++)
    {
        int x = i,y = 0;
        while(x)
        {
            int ds = get_dis(x,i);
            tr1.push(x,ds,v[i]);
            if(y)tr2.push(y,ds,v[i]);
            y=x,x=uf[x];
        }
    }
    int opt,x,y,a,b,ds,ans = 0;
    for(int i=1;i<=m;i++)
    {
        opt = rd(),x = rd()^ans,y = rd()^ans;
        if(!opt)
        {
            a = x,b = 0;
            ans = 0;
            while(a)
            {
                ds = y - get_dis(a,x);
                if(ds>=0)
                {
                    ans+=tr1.ask(a,ds);
                    if(b)ans-=tr2.ask(b,ds);
                }
                b = a,a = uf[a];
            }
            printf("%d
",ans);
        }else
        {
            int dv = y - v[x];
            v[x] = y;
            a = x,b = 0;
            while(a)
            {
                ds = get_dis(a,x);
                tr1.push(a,ds,dv);
                if(b)tr2.push(b,ds,dv);
                b = a,a = uf[a];
            }
        }
    }
    return 0;
}

 

以上是关于bzoj3730 震波的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3730: 震波

BZOJ3730震波 动态树分治+线段树

bzoj 3730 震波 (动态点分治)

bzoj3730. 震波

[bzoj3730] 震波

BZOJ 3730 震波