Bzoj3786星系探索:splay维护dfs序

来源:互联网 发布:matlab矩阵相加 编辑:程序博客网 时间:2024/05/18 20:47

题目链接:星系探索

最近越来越懒了都不想写blog了QAQ

子树修改,链查询,树结构改变,单纯的lct已经不能满足这道题了QAQ

考虑dfs序,设每个点再dfs序中的位置为st[x],ed[x],我们在st[x]的位置上赋值为x的值,在ed[x]上赋值为-x的值,这样查询链的时候不在链上的点的贡献会被抵消

修改也很简单

至于改变父节点,只要把当前子树的那一段dfs序删去并加在新父节点的后面即可

然而这个代码在BZ上迷之RE在本地机上AC是什么鬼?

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#define LL long longusing namespace std;const int maxn=200051;int n,m,a[maxn],fz[maxn],w[maxn],sta[maxn];int st[maxn],ed[maxn],root,tot=0,h[maxn],ind=0;struct edge{int to,next;}G[maxn];struct Nodes{int c[2],s0,s1,add,fa;LL s;};struct splay_tree{Nodes t[maxn];void push_up(int x){t[x].s0=t[t[x].c[0]].s0+t[t[x].c[1]].s0+(w[x]==1);t[x].s1=t[t[x].c[0]].s1+t[t[x].c[1]].s1+(w[x]==-1);t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+fz[x];}void update(int x,int v){if (!x) return;t[x].s+=1LL*(t[x].s0-t[x].s1)*v;fz[x]+=w[x]*v;t[x].add+=v;}void push_down(int x){if (!t[x].add||!x) return;update(t[x].c[0],t[x].add);update(t[x].c[1],t[x].add);t[x].add=0;}void pre(int x){int top=0; for (;x;x=t[x].fa) sta[++top]=x;while (top) push_down(sta[top--]);}void rotate(int p,int x){        int mark= p==t[x].c[1];        int y=t[p].c[mark^1],z=t[x].fa;        if (t[z].c[0]==x) t[z].c[0]=p;        if (t[z].c[1]==x) t[z].c[1]=p;        if (y) t[y].fa=x; t[x].c[mark]=y;        t[p].fa=z; t[p].c[mark^1]=x; t[x].fa=p;        push_up(x);    } void splay(int p,int k){pre(p);        while (t[p].fa!=k){            int x=t[p].fa,y=t[x].fa;            if (y==k) rotate(p,x);            else if (p==t[x].c[0]^x==t[y].c[0]) rotate(p,x),rotate(p,y);            else rotate(x,y),rotate(p,x);        } push_up(p);        if (!k) root=p; return;    }int findmin(int x){while (t[x].c[0]) x=t[x].c[0];return x;}int findmax(int x){while (t[x].c[1]) x=t[x].c[1];return x;}void split(int x,int y){splay(x,0);int t1=findmax(t[x].c[0]);splay(y,0);int t2=findmin(t[y].c[1]);splay(t1,0);splay(t2,root);}void build(int l,int r,int fat){if (l>r) return;int mid=(l+r)>>1;t[mid].fa=fat;if (fat) t[fat].c[mid>fat]=mid;if(l==r){t[l].s=fz[l];t[l].s0=w[l]==1;t[l].s1=1-t[l].s0;return;}build(l,mid-1,mid); build(mid+1,r,mid);push_up(mid);}void work1(){        int x; scanf("%d",&x);splay(1,0); splay(st[x],root);printf("%lld\n",t[t[t[root].c[1]].c[0]].s+fz[root]+fz[t[root].c[1]]);}void work2(){        int x,y; scanf("%d%d",&x,&y);splay(st[x],0); splay(ed[x],root);update(t[t[root].c[1]].c[0],y);fz[root]+=w[root]*y;fz[t[root].c[1]]+=w[t[root].c[1]]*y;push_up(t[root].c[1]);push_up(root);}void work3(){int x,y; scanf("%d%d",&x,&y);split(st[x],ed[x]);int tmp=t[root].c[1],tmp2=t[tmp].c[0];t[tmp].c[0]=0;push_up(tmp); push_up(root);splay(st[y],0);splay(findmin(t[root].c[1]),root);t[t[root].c[1]].c[0]=tmp2;t[tmp2].fa=t[root].c[1];push_up(t[root].c[1]); push_up(root);}}s;void add(int x,int y){G[++tot].to=y;G[tot].next=h[x];h[x]=tot;}void dfs(int x){st[x]=++ind; fz[ind]=a[x]; w[ind]=1;for (int i=h[x];i;i=G[i].next) if (!st[G[i].to]) dfs(G[i].to);ed[x]=++ind; fz[ind]=-a[x]; w[ind]=-1;}int main(){scanf("%d",&n);for (int i=2;i<=n;++i){int x; scanf("%d",&x);add(x,i);}for (int i=1;i<=n;++i) scanf("%d",&a[i]);ind=1;dfs(1);s.build(1,ind+1,0);scanf("%d",&m);for (int i=1;i<=m;++i){char ch; cin>>ch;if (ch=='Q') s.work1();else if (ch=='F') s.work2();else if (ch=='C') s.work3();}}


2 0
原创粉丝点击