您好,欢迎来到微智科技网。
搜索
您的当前位置:首页BZOJ3786: 星系探索 splay维护dfs序

BZOJ3786: 星系探索 splay维护dfs序

来源:微智科技网

题目大意:n个点的树,m个操作
1.询问到根权值和
2.改变父亲,保证不出环
3.子树加
n<=100000,m<=300000,要开long long
toptree轻松虐,可惜我不会
因为本题的询问都是一个点到根的,根又不会变,因此可以通过维护入栈出栈序的方法,每个点入栈时向splay中push _ back一个正权值点,出栈时向splay中push _ back一个负权值点,这样从头到查询点之间的其它点会正负抵消。
改变父亲就将这个点入栈——出栈之间的一段提出来,插到父亲的入栈点之后。
入栈点cnt记为1,出栈点记为-1,则add标记对sum的增加量就是cnt之和*add,入栈点v+=add,出栈点v-=add。
注意权值有0,因此不能靠权值的正负来判断是入栈点还是出栈点,要单独记录。

#include<cstdio>
#define gm 100001
using namespace std;
typedef long long ll;
typedef const ll& cref;
struct node
{
    ll sum,v,add;
    char inv;
    int cnt;
    node *s[2],*f;
    node();
    node(cref,char);
    inline void* operator new(size_t)
    {
        static unsigned char p[gm*sizeof(node)*2];
        static size_t t=-1;
        return ((node*)p)+ ++t;
    }
    inline bool r()
    {
        return this==f->s[1];
    }
    inline void up()
    {
        sum=v+s[0]->sum+s[1]->sum;
        cnt=inv+s[0]->cnt+s[1]->cnt;
    }
    inline void plus(cref);
    inline void down();
}*nil=new node;
node::node():sum(0),v(0),add(0),cnt(0),f(nil){s[0]=s[1]=nil;}
node::node(cref v,char inv):sum(v),v(v),add(0),inv(inv),cnt(inv),f(nil){s[0]=s[1]=nil;}
inline void node::plus(cref a)
{
    if(this==nil) return;
    add+=a;
    if(~inv) v+=a;else v-=a;
    sum+=cnt*a;
}
inline void node::down()
{
    if(f!=nil) f->down();
    if(add)
    s[0]->plus(add),s[1]->plus(add),add=0;
}
struct SplayTree
{
    typedef node* Iterator;
    node *rt;
    SplayTree(node *rt=nil):rt(rt){}
    inline void rot(node *x)
    {
        static node *o,*y;
        static bool k;
        k=!x->r();
        o=x->f,y=x->s[k];
        if(o->f!=nil) o->f->s[o->r()]=x;
        x->s[k]=o,o->s[!k]=y;
        x->f=o->f,o->f=x,y->f=o;
        o->up();
    }
    inline void splay(node *x)
    {
        x->down();
        while(x->f!=nil)
        {
            if(x->f->f==nil) rot(x);
            else if(x->r()==x->f->r()) rot(x->f),rot(x);
            else rot(x),rot(x);
        }
        rt=x;
        x->up();
    }
    inline void push_back(node *x)
    {
        if(rt==nil) {rt=x;return;}
        node *now=rt;
        while(now->s[1]!=nil) now=now->s[1];
        splay(now);
        now->s[1]=x;
        x->f=now;
        now->up();
    }
    inline node* push_back(cref v,char t)
    {
        node *x=new node(v,t);
        push_back(x);
        return x;
    }
    inline void push_back(SplayTree& v)
    {
        push_back(v.rt);
        v.rt=nil;
    }
    inline SplayTree split_before(node *x)
    {
        splay(x);
        x=rt->s[0];
        rt->s[0]=x->f=nil;
        rt->up();
        return SplayTree(x);
    }
    inline SplayTree split_after(node *x)
    {
        splay(x);
        x=rt->s[1];
        rt->s[1]=x->f=nil;
        rt->up();
        return SplayTree(x);
    }
    inline void add(cref v)
    {
        rt->plus(v);
    }
    inline ll sum()
    {
        return rt->sum;
    }
}tree;
int n,m,fat[gm],w[gm];
char c;
SplayTree::Iterator begin[gm],end[gm];
struct e
{
    int t;
    e *n;
    e(int t,e *n):t(t),n(n){}
}*f[gm];
void dfs(int x)
{
    begin[x]=tree.push_back(ll(w[x]),1);
    for(e *i=f[x];i;i=i->n)
    if(i->t!=fat[x])
    dfs(i->t);
    end[x]=tree.push_back(ll(-w[x]),-1);
}
inline ll query(int x)
{
    SplayTree arc=tree.split_after(begin[x]);
    ll ans=tree.sum();
    tree.push_back(arc);
    return ans;
}
inline void reset(int x,int y)
{
    SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]);
    pre.push_back(arc);
    arc=pre.split_after(begin[y]);
    tree.push_back(arc);
    pre.push_back(tree);
    tree.push_back(pre);
}
inline void add(int x,ll v)
{
    SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]);
    tree.add(v);
    tree.push_back(arc);
    pre.push_back(tree);
    tree.push_back(pre);
}
int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;++i)
    {
        scanf("%d",fat+i);
        f[fat[i]]=new e(i,f[fat[i]]);
    }
    for(int i=1;i<=n;++i)
    scanf("%d",w+i);
    dfs(1);
    scanf("%d",&m);
    while(m--)
    {
        do c=getchar();while(c!='Q'&&c!='C'&&c!='F');
        if(c=='Q')
        {
            int d;
            scanf("%d",&d);
            printf("%lld\n",query(d));
        }
        else if(c=='C')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            reset(x,y);
        }
        else
        {
            int p,q;
            scanf("%d%d",&p,&q);
            add(p,q);
        }
    }
    return 0;
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务