poj2481~Cows~(树状数组)

本文介绍了一个使用树状数组解决区间覆盖问题的方法,详细解释了算法思路,并提供了具体的实现代码。通过实例演示了如何高效地计算每个区间的覆盖情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:一群区间,问你对于每个区间,他被多少个区间覆盖?例如2-4就是被1-5覆盖的,但是需要区间长度不能相等,例如2-4是被2-5覆盖,但是不被2-4覆盖。

思路:树状数组。继续直接用例子来讲思路吧。

样例:

4

1 3

1 3

4 5

4 6

2 6

 

首先,我会将以区间的终点为依据进行降序排序,如果终点相等就对起点升序排序,排完后就变成了这样:

终点:6 6 5 3 3

起点:2 4 4 1 1

序号:1 2 3 4 5

好,看第一个区间,肯定没有区间能覆盖他,因为他的终点是最大的,起点又是最小的。 然后将起点2插入树状数组c,表示2处有一个点

看第二个区间,它的起点是4,通过sum函数,判断出4前面有一个点,说明有一个区间覆盖了它,保存进ans数组。然后再将4插入树状数组c

继续看第三个区间,起点也是4,通过sum函数判断出4前面有2个点(包括4)。

同理第四个

第五个就有点特别了,1 3和1 3是一样的,所以他们的结果应该是一样的,而不是+1,所以直接赋予和它一样的答案。

具体实现过程请看代码。详细的注释哦

#include<iostream>
#include<string>
#include<algorithm>
#define M 100005
using namespace std;

int c[M],n,ans[M];
struct COW
{
	int s,e,num;
};
COW cow[M];


int cmp(struct COW &a,struct COW &b)
{
	if(a.e>b.e)
		return 1;
	else if(a.e==b.e)    //如果终点相同,比较起点,让起点小的在前面
	{
		if(a.s<b.s)
			return 1;
		else return 0;
	}
	else return 0;
}

int  sum(int i)    //查询0到i区间的数值状况
{
	int s=0;
	while(i>0)
	{
		s+=c[i];
		i-=i&(-i);
	}
	return s;
}

void update(int i,int value)//更新i点的数值状况
{
	while(i<=n)
	{
		c[i]+=value;
		i+=i&(-i);
	}
}


int main()
{
	int i,j;
	while(scanf("%d",&n),n!=0)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&cow[i].s,&cow[i].e);
			cow[i].num=i;      //记录原来的序号,因为要按原顺序输出答案
			cow[i].s++;cow[i].e++;//好像我上面那个update函数中i为0的话会有问题,就每个加一了
		}
		
		sort(cow+1,cow+1+n,cmp);    //对终点进行降序排序
		memset(c,0,sizeof(c));     //初始化
		
		for(i=1;i<=n;i++)
		{
			if(cow[i].s==cow[i-1].s&&cow[i].e==cow[i-1].e)  //排除了区间相等的情况
				ans[cow[i].num]=ans[cow[i-1].num];
			else 
				ans[cow[i].num]=sum(cow[i].s);       //ans=0到s之间的点的个数
			update(cow[i].s,1);                     //更新
		}
		
		for(i=1;i<=n;i++)               //注意输出格式
		{
			printf("%d",ans[i]);
			if(i!=n) printf(" ");
			else printf("\n");
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值