• bzoj3786 星系探索


    题面:

    物理学家小C的研究正遇到某个瓶颈。

    他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。

    我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.

    对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.

    每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。

    但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。

    有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。

    现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。

    学长出的题啊。。。

    欧拉序+splay,将每个点按dfs序分成两个点,然后进行:

    1.区间求和(splay基础)

    2.区间加法(还是splay基础)

    3.区间移动(其实就是删除+插入)

    需要注意的是区间加法。为了维护前缀和的正确性,标记下推时应程一个系数(1 、-1)。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ll long long
    ll n,m,hed[N],cnt;
    struct EDGE
    {
        ll to,nxt;
    }e[N];
    void ae(ll f,ll t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    struct Splay
    {
        ll ch[2],fa,vl,siz,sum,mrk;
        ll kk,sk;
    }tr[2*N];
    ll tin[N],tout[N],tot=1,a[N],rt;
    void dfs(ll u)
    {
        tin[u]=++tot;
        tr[tot].vl = a[u];
        tr[tot].kk = 1;
        tr[tot].sk = 1;
        for(ll j=hed[u];j;j=e[j].nxt)dfs(e[j].to);
        tout[u]=++tot;
        tr[tot].vl = -a[u];
        tr[tot].kk = -1;
        tr[tot].sk = -1;
    }
    void update(ll u)
    {
        ll l = tr[u].ch[0],r = tr[u].ch[1];
        tr[u].siz = tr[l].siz+tr[r].siz+1;
        tr[u].sk = tr[l].sk+tr[r].sk+tr[u].kk;
        tr[u].sum = tr[l].sum+tr[r].sum+tr[u].vl;
    }
    void pushdown(ll x)
    {
        ll l = tr[x].ch[0],r = tr[x].ch[1],k = tr[x].mrk;
        if(k)
        {
            if(l)tr[l].vl+=k*tr[l].kk,tr[l].sum+=tr[l].sk*k,tr[l].mrk+=k;
            if(r)tr[r].vl+=k*tr[r].kk,tr[r].sum+=tr[r].sk*k,tr[r].mrk+=k;
            tr[x].mrk=0;
        }
    }
    void build(ll l,ll r,ll f)
    {
        if(l>r)return ;
        ll mid = (l+r)>>1;
        if(l!=r)build(l,mid-1,mid),build(mid+1,r,mid);
        tr[mid].fa = f;
        tr[f].ch[mid>=f] = mid;
        update(mid);
    }
    void rotate(ll x)
    {
        ll y = tr[x].fa,z = tr[y].fa,k = (tr[y].ch[1]==x);
        tr[y].ch[k] = tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa = y;
        tr[x].ch[k^1] = y,tr[y].fa = x;
        tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa = z;
        update(y),update(x);
    }
    void splay(ll x,ll goal)
    {
        while(tr[x].fa!=goal)
        {
            ll y = tr[x].fa,z = tr[y].fa;
            if(z!=goal)
                ((tr[y].ch[1]==x)^(tr[z].ch[1]==y))?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)rt = x;
    }
    ll get_th(ll x)
    {
        ll ret = 0;
        if(x==rt)ret = tr[tr[x].ch[0]].siz+1;
        else if(x==tr[tr[x].fa].ch[0])ret = get_th(tr[x].fa)-1-tr[tr[x].ch[1]].siz;
        else ret = get_th(tr[x].fa)+1+tr[tr[x].ch[0]].siz;
        pushdown(x);
        return ret;
    }
    ll find_kth(ll x,ll k)
    {
        pushdown(x);
        ll t = tr[tr[x].ch[0]].siz;
        if(k<=t)return find_kth(tr[x].ch[0],k);
        else if(k==t+1)return x;
        else return find_kth(tr[x].ch[1],k-1-t);
    }
    void ccc(ll x,ll y)
    {
        ll l,r;
        l = get_th(tin[x])-1,r = get_th(tout[x])+1;
        l = find_kth(rt,l),r = find_kth(rt,r);
        splay(l,0),splay(r,l);
        ll z = tr[tr[rt].ch[1]].ch[0];
        tr[tr[z].fa].ch[0]=0;
        update(tr[z].fa),update(rt);
        l = get_th(tin[y]),r = l+1;
        l = find_kth(rt,l),r = find_kth(rt,r);
        splay(l,0),splay(r,l);
        tr[z].fa = tr[rt].ch[1];
        tr[tr[rt].ch[1]].ch[0] = z;
        update(tr[z].fa),update(rt);
    }
    void fff(ll x,ll d)
    {
        ll l,r;
        l = get_th(tin[x])-1;
        r = get_th(tout[x])+1;
        l = find_kth(rt,l),r = find_kth(rt,r);
        splay(l,0),splay(r,l);
        ll z = tr[r].ch[0];
        tr[z].mrk+=d;
        tr[z].vl+=d*tr[z].kk;
        tr[z].sum+=d*tr[z].sk;
    }
    int main()
    {
        scanf("%lld",&n);
        for(ll f,i=2;i<=n;i++)
        {
            scanf("%lld",&f);
            ae(f,i);
        }
        for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
        dfs(1);
        build(1,2*n+2,0);
        rt = (2*n+3)>>1;
        scanf("%lld",&m);
        char ch[2];
        ll x,y;
        for(ll i=1;i<=m;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                scanf("%lld",&x);
                get_th(tin[x]);
                splay(tin[x],0);
                printf("%lld
    ",tr[tr[rt].ch[0]].sum+tr[rt].vl);
            }else if(ch[0]=='C')
            {
                scanf("%lld%lld",&x,&y);
                ccc(x,y);
            }else
            {
                scanf("%lld%lld",&x,&y);
                fff(x,y);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    js:delete 操作符
    ActiveReports 代码控制报表连续打印
    ActiveReports 打印条码无法设置纸张大小?
    《JavaScript高级程序设计》读书笔记之一:几个与原始类型等价的引用类型的常用方法和属性
    js:字符串类型快速转化成数字类型和数字类型快速转化为字符串类型
    js:for...in 语句(JavaScript For...In Statement)
    Internet Explorer Developer Toolbar
    javascript 定义对象的方法
    关于 输入框输入一定数以后跳转的问题
    javascript 关于弹出关闭的例子
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9615808.html
Copyright © 2020-2023  润新知