Bzoj3786星系探索:splay維護dfs序

題目鏈接:星系探索

最近越來越懶了都不想寫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 long
using 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();
	}
}


發佈了112 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章