bzoj3786-星系探索

题目

一颗带点权的树,根为1,实现下列三种操作:

  • \(Q\ x\) 求点\(x\)到根的点权和
  • \(C\ x\ y\)\(x\)的父亲换成\(y\)
  • \(F\ x\ y\)\(x\)的子树中每个点的点权点权增加\(y\)

    分析

    写了一半发现lct做不了,因为有子树修改。然而zwl说,由于树的形态没有改变,可以通过维护lct的一些东西解决。toptree模板题,但是不会写。于是有一个神奇方法——dfs序(欧拉序)。我们把每个点的入栈和出栈时间用一个splay维护,那么就可以很方便的修改子树(splay标记),换父亲(区间移动)。现在问题是怎么求到根的点权和。这里有一个很精妙的做法:我们把入栈时的点设为正,出栈设为负,那么欧拉序前缀和就是点到根的点权和。因为如果已经出栈了的点是不在这个点到根的链上的。这样做就很简单了。

代码

一定要记得,splay在insert的时候是要不断下传标记的。一开始就这里错了。

#include<cstdio>
#include<algorithm>
#include<cctype>
#define F(x) for (giant i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
using namespace std;
typedef long long giant;
giant read() {
    giant x=0,f=1;
    char c=getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const giant maxn=1e5+10;
const giant inf=1e9+10;
giant val[maxn],dft=1,first[maxn],second[maxn];
struct node {
    giant v,sum,fa,ch[2],sta,tag,gs,ps,ns;
    bool inv;
} t[maxn<<2];
struct edge {
    giant v,nxt;
} e[maxn<<1];
giant h[maxn],tot=0;
void add(giant u,giant v) {
    e[++tot]=(edge){v,h[u]};
    h[u]=tot;
}
giant root;
bool rson(giant x) {
    return t[t[x].fa].ch[1]==x;
}
giant pos(giant x) {
    giant now=x,ret=t[t[x].ch[0]].gs+1;
    while (now) {
        if (rson(now)) ret+=t[t[t[now].fa].ch[0]].gs+1;
        now=t[now].fa;
    }
    return ret;
}
giant find(giant x) {
    giant now=root;
    while (true) {
        giant tmp=t[t[now].ch[0]].gs+1;
        if (x==tmp) return now; else
        if (x>tmp) x-=tmp,now=t[now].ch[1]; else
        if (x<tmp) now=t[now].ch[0];
    }
    return 0;
}
void doit(giant x,giant y) {
    if (!x) return;
    t[x].tag+=y;
    t[x].v+=y;
    t[x].sum+=(t[x].ps-t[x].ns)*y;
}
void push(giant x) {
    if (!t[x].tag) return;
    giant l=t[x].ch[0],r=t[x].ch[1];
    if (l) doit(l,t[x].tag);
    if (r) doit(r,t[x].tag);
    t[x].tag=0;
}
void update(giant x) {
    push(x);
    t[x].gs=t[t[x].ch[0]].gs+t[t[x].ch[1]].gs+1;
    t[x].ps=t[t[x].ch[0]].ps+t[t[x].ch[1]].ps+(t[x].sta==1);
    t[x].ns=t[t[x].ch[0]].ns+t[t[x].ch[1]].ns+(t[x].sta==-1);
    t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].v*t[x].sta;
}
void rotate(giant x) {
    giant f=t[x].fa,d=rson(x),c=t[x].ch[d^1];
    if (t[f].fa) t[t[f].fa].ch[rson(f)]=x;
    if (c) t[c].fa=f;
    t[x].fa=t[f].fa,t[f].fa=x,t[x].ch[d^1]=f,t[f].ch[d]=c;
    update(f),update(x);
}
void down(giant x) {
    if (t[x].fa) down(t[x].fa);
    push(x);
}
void splay(giant x,giant d=0) {
    down(x);
    while (t[x].fa!=d) {
        if (t[t[x].fa].fa==d) rotate(x); else {
            if (rson(x)==rson(t[x].fa)) {
                rotate(t[x].fa);
                rotate(x);
            } else {
                rotate(x);
                rotate(x);
            }
        }
    }
    if (!d) root=x;
}
void insert(giant p,giant x) {
    if (!root) {
        update(x);
        t[root=x].gs=1;
        return;
    }
    giant now=root;
    while (now) {
        push(now);
        giant tmp=t[t[now].ch[0]].gs+1;
        giant &a=t[now].ch[p>=tmp];
        p-=(p>=tmp)*tmp;
        if (a) now=a; else {
            a=x;
            t[x].fa=now;
            update(x);
            break;
        }
    }
    for (;now;now=t[now].fa) update(now);
    splay(x);
}
giant range(giant x,giant y) {
    giant px=pos(x);
    giant bf=find(px-1);
    splay(bf);
    giant py=pos(y);
    giant af=find(py+1);
    splay(af,bf);
    return t[af].ch[0];
}
void dfs(giant x,giant fa) {
    first[x]=++dft;
    t[dft].sta=1;
    t[dft].v=val[x];
    insert(dft-1,dft);
    F(x) if (v!=fa) dfs(v,x);
    second[x]=++dft;
    t[dft].sta=-1;
    t[dft].v=val[x];
    insert(dft-1,dft);
}
int main() {
    #ifndef ONLINE_JUDGE
        freopen("test.in","r",stdin);
        freopen("my.out","w",stdout);
    #endif
    giant n=read();
    for (giant i=2;i<=n;++i) {
        giant x=read();
        add(i,x),add(x,i);
    }
    for (giant i=1;i<=n;++i) val[i]=read();
    insert(0,1); // because of this node, all the ids have to be increased by one.
    dfs(1,0);
    insert(n*2+1,n*2+2);
    giant m=read();
    while (m--) {
        static char o[3];
        scanf("%s",o);
        if (o[0]=='Q') {
            giant x=read();
            giant now=range(2,first[x]);
            printf("%lld\n",t[now].sum);
            splay(now);
        } else if (o[0]=='C') {
            giant x=read(),y=read();
            giant nx=range(first[x],second[x]);
            giant f=t[nx].fa;
            bool rs=rson(nx);
            t[f].ch[rs]=0,t[nx].fa=0;
            update(f);
            insert(pos(first[y]),nx);
        } else if (o[0]=='F') {
            giant x=read(),y=read();
            giant now=range(first[x],second[x]);
            doit(now,y);
            splay(now);
        }
    }
}

转载于:https://www.cnblogs.com/owenyu/p/6724693.html

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
weixin102旅游社交微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值