Bzoj4196:[Noi2015]軟件包管理器:樹鏈剖分

題目鏈接:4196:[Noi2015]軟件包管理器

這是一道沙茶題

昨天寫一道樹鏈剖分題調了3h最後莫名其妙地過了被人D了一頓

今天我不服我要秒A一道樹鏈剖分給你們看看

然而……

建立線段樹的時候寫成了這個"p->l;p->r=r;"

然後調了1hQAQ

交了一發E了

又調了0.5h,發現dfs1(int x,int deep)中對兒子進行dfs時寫成了dfs1(v,x)QAQ

兩個小時才A感覺已經沒救了……

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=300010;
int n,m,tot=0,h[maxn],fa[maxn],ind=0,Ans;
struct seg{
	int l,r;
	int s,data;
	seg *lc,*rc;
	seg():s(0),data(0){}
};
seg *root=new seg();
struct edge{int to,next;}G[maxn*2];
int s[maxn],pos[maxn],Belong[maxn],dep[maxn];
char str[200];

void add(int x,int y){
	G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}

void dfs1(int x,int deep){
	dep[x]=deep; s[x]=1;
	for (int i=h[x];i;i=G[i].next){
		int v=G[i].to;
		if (v==fa[x]) continue;
		fa[v]=x; dfs1(v,deep+1); s[x]+=s[v];
	}
}

void dfs2(int x,int L){
	++ind; pos[x]=ind; Belong[x]=L; int k=0;
	for (int i=h[x];i;i=G[i].next)
	    if (dep[G[i].to]>dep[x]&&s[G[i].to]>s[k])
	        k=G[i].to;
	if (!k) return; dfs2(k,L);
	for (int i=h[x];i;i=G[i].next)
	    if (dep[G[i].to]>dep[x]&&G[i].to!=k)
	        dfs2(G[i].to,G[i].to);
}

void build(seg *p,int l,int r){
	p->l=l; p->r=r;
	if(l+1==r){p->s=0;p->lc=p->rc=NULL;return;}
	else if (l+1<r){
		int mid=(l+r)>>1;
		p->lc=new seg();
		p->rc=new seg();
		if (l<mid) build(p->lc,l,mid);
		else p->lc=NULL;
		if (mid<r) build(p->rc,mid,r);
		else p->rc=NULL;
	}
}

void push_down(seg *p){
	if (p->l+1==p->r) return;
 	if (p->data==1){
		if (p->lc!=NULL) p->lc->s=p->lc->r - p->lc->l,p->lc->data=1;
		if (p->rc!=NULL) p->rc->s=p->rc->r - p->rc->l,p->rc->data=1;
	}else if (p->data==2){
		if (p->lc!=NULL) p->lc->s=0,p->lc->data=2;
		if (p->rc!=NULL) p->rc->s=0,p->rc->data=2;
	}p->data=0;
}

void ask1(seg *p,int l,int r){
	if (l<=p->l&&p->r<=r){Ans+=p->s;return;}
	push_down(p);
	int mid=(p->l+p->r)>>1;
	if (l<mid) ask1(p->lc,l,r);
	if (mid<r) ask1(p->rc,l,r);
}

void ask0(seg *p,int l,int r){
    if (l<=p->l&&p->r<=r){Ans+=(p->r-p->l)-p->s;return;}
	push_down(p);
	int mid=(p->l+p->r)>>1;
	if (l<mid) ask0(p->lc,l,r);
	if (mid<r) ask0(p->rc,l,r);
}

void push_up(seg *p){
	if (p->l+1==p->r) return;
	p->s=0;
	if (p->lc) p->s+=p->lc->s;
	if (p->rc) p->s+=p->rc->s;
}

void change(seg *p,int l,int r,bool flag){
	if(l<=p->l&&p->r<=r)
		if(flag==1){p->s=p->r-p->l;p->data=1;return;}
		else{p->s=0;p->data=2;return;}
	push_down(p);
	int mid=(p->l+p->r)>>1;
	if (l<mid) change(p->lc,l,r,flag);
	if (mid<r) change(p->rc,l,r,flag);
	push_up(p);
}

int query1(int x,int y){
	int sum=0;
	while (Belong[x]!=Belong[y]){
		if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
		Ans=0; ask1(root,pos[Belong[x]],pos[x]+1);
		sum+=Ans; x=fa[Belong[x]];
	}
	if (dep[x]<dep[y]) swap(x,y);
	Ans=0; ask1(root,pos[y],pos[x]+1);
	sum+=Ans; return sum;
}

int query0(int x,int y){
    int sum=0;
	while (Belong[x]!=Belong[y]){
		if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
		Ans=0; ask0(root,pos[Belong[x]],pos[x]+1);
		sum+=Ans; x=fa[Belong[x]];
	}
	if (dep[x]<dep[y]) swap(x,y);
	Ans=0; ask0(root,pos[y],pos[x]+1);
	sum+=Ans; return sum;
}

void changel(int x,int y){
	while (Belong[x]!=Belong[y]){
        if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
		change(root,pos[Belong[x]],pos[x]+1,1);
		x=fa[Belong[x]];
	}
	if (dep[x]<dep[y]) swap(x,y);
	change(root,pos[y],pos[x]+1,1);
}

void work1(){
	int x; scanf("%d",&x); x++;
	printf("%d\n",query0(x,1));
	changel(x,1);
}

void work2(){
	int x; scanf("%d",&x); x++;
	Ans=0; ask1(root,pos[x],pos[x]+s[x]);
	printf("%d\n",Ans);
	change(root,pos[x],pos[x]+s[x],0);
}

int main(){
	scanf("%d",&n);
	for (int i=1;i<n;++i){
		int x; scanf("%d",&x); x++;
		add(x,i+1); 
	}
	dfs1(1,0); dfs2(1,1);
	build(root,1,n+1);
	scanf("%d",&m);
	for (int i=1;i<=m;++i){
		scanf("%s",str);
		if (str[0]=='i') work1();
		else work2();
	}
}


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