hdu 3577 Fast Arrangement(线段树+懒惰标记(pushdown函数))

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3577
题目大意:

有一火车,最多能坐k个人,现在有Q个乘客,A站上车,B站下车,如果该乘客能上车 输出ta的编号,否则继续下一个乘客。

分析:

    好久没做线段树的题目,结果bug连连出,还有以前做线段树的时候,效果也不是很好,刷的题目也不够,没有深入理解。
    回归此题:

  • 首先要注意的是乘客从b站下车,故更新与查询的区间都是[a,b-1]
  • 对于pushdown函数,我开始是这样写的:
void pushdown(int rt)
{
	tr[rt<<1].add+=tr[rt].add;
	tr[rt<<1|1].add+=tr[rt].add;
	tr[rt<<1].val+=tr[rt<<1].add;
	tr[rt<<1|1].val+=tr[rt<<<1}1].add;
	tr[rt].add=0;
}

结果找了好久,o(╯□╰)o, 因为我程序中每次更新是将add+1,同时val也+1,因此tr[rt].add是表示其子孙有待更新的,而不是其本身,像这上面的tr[rt<<1].val+=tr[rt<<1].add;就会是tr[rt<<1]的add值重复计算一遍

代码:
#include <bits/stdc++.h>

using namespace std;
const int N=1e6+5;
//query,和update都要  懒惰标记

struct tr
{
	int left,right;
	int val;
	int add;// 延迟标记
	
}tr[N<<2];
int arc[N];//用来存编号
void pushup(int rt)
{
	tr[rt].val=max(tr[rt<<1].val,tr[rt<<1|1].val);
}

void pushdown(int rt)
{
	tr[rt<<1].add+=tr[rt].add;
	tr[rt<<1|1].add+=tr[rt].add;
	tr[rt<<1].val+=tr[rt].add;
	tr[rt<<1|1].val+=tr[rt].add;
	tr[rt].add=0;
}

void build(int l,int r,int rt)
{
	tr[rt].left=l;
	tr[rt].right=r;
	tr[rt].add=0;
	tr[rt].val=0;

	if(l==r)
		return;
	int mid=l+r>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	pushup(rt);
}

void update(int l,int r,int rt)
{
	if(l<=tr[rt].left&&r>=tr[rt].right)
	{
		tr[rt].add+=1;
		tr[rt].val+=1;
		return;
	}
	if(tr[rt].add) pushdown(rt);
	int mid=tr[rt].left+tr[rt].right>>1;
	if(l<=mid) update(l,r,rt<<1);
	if(r>mid) update(l,r,rt<<1|1);
	pushup(rt);
}


int query(int l,int r,int rt)
{
	if(tr[rt].left>=l&&tr[rt].right<=r)
	{
		return tr[rt].val;
	}
	
	if(tr[rt].add) pushdown(rt);
	int mid=tr[rt].left+tr[rt].right>>1;
	if(r<=mid)
	{
		return query(l,r,rt<<1);
	}
	else if(l>mid)
		return query(l,r,rt<<1|1);
	else
		return max(query(l,r,rt<<1),query(l,r,rt<<1|1));

}

int main()
{
	
	int t;
	int k, q;
	int a,b;
	scanf("%d",&t);
	int ok=0;
	while(t--)
	{
		scanf("%d%d",&k,&q);
		build(1,1000000,1);
		
		
		int cnt=0;
		for(int i=1;i<=q;i++)
		{
			scanf("%d%d",&a,&b);
			if(query(a,b-1,1)<k)
			{
				update(a,b-1,1);
				arc[cnt++]=i;
			}
		}
		printf("Case %d:\n",++ok);
		for(int i=0;i<cnt-1;i++)
			printf("%d ",arc[i]);
		printf("%d \n\n",arc[cnt-1]);
	}
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值