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();
	}
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值