【题解】vijos 最高的牛

仔细观察数据可以发现,如果要求可能最大的每头牛的高度,只需要将给出的区间(注意是开区间)内的数减去1就行了。然而只能得50分。因为还要判断一下是否之前输入过这个区间,否则会重复减去。

当然 上面的做法并不是最优,因为数组开的太大了,只是由于在线评测你用多少空间机器给你多少空间,正式比赛会全部MLE。我们还有判重的优化做法。就是将读入的区间存在结构体里,并将结构体按照x大小排序,在做减法之前,我们扫一遍结构体,如果两个相邻的数x和y都相等,那么就把x+1和y+1给设为0,来达到判重的效果。经这个过程后我们能得到更快的正解

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,i,h,r;
struct edge
{
	int x;
	int y;
}a[10010];
int t[10010];
bool cmp(const edge &a,const edge &b)
{
	return a.x<b.x;
}
int main()
{
	scanf("%d%d%d%d",&n,&i,&h,&r);
	for(int i=1;i<=n;i++)
	{
		t[i]=h;
	}
	for(int i=1;i<=r;i++)
	{
		cin>>a[i].x>>a[i].y;
	}
	sort(a+1,a+r+1,cmp);
	for(int i=1;i<=r;i++)
	{
		if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y)
		{
			a[i+1].x=0;
			a[i+1].y=0;
		}
	}
	for(int i=1;i<=r;i++)
	{
		if(a[i].x==a[i].y||abs(a[i].x-a[i].y==1))
		{
			continue;
		}
		if(a[i].x<a[i].y)
		{
			for(int j=a[i].x+1;j<=a[i].y-1;j++)
			{
				t[j]--;
			}
			continue;
		}
		if(a[i].x>a[i].y)
		{
			for(int j=a[i].x-1;j>=a[i].y+1;j--)
			{
				t[j]--;
			}
			continue;
		}
	}

	for(int i=1;i<=n;i++)
	{
		cout<<t[i]<<endl;
	}
			
	return 0;
}

不过算一下时间复杂度,我们在去重的操作时最坏的情况的时间复杂度近似等于O(n^2),对这道题的n<=10000理论上是会TLE的,所以我们需要考虑前缀和做法。首先,我们可以初始化f数组为0,如果在某个区间内,就将它加1,最后输出h-f[i]就是正确的答案,然后对于读入的区间,我们在其头上+1,末尾的下一位-1,最后求前缀和即可,注意区间是开区间。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,i,h,r;
struct edge
{
	int x;
	int y;
}a[10010];
int f[10010];

bool cmp(const edge &a,const edge &b)
{
	return a.x<b.x;
}
int main()
{
	scanf("%d%d%d%d",&n,&i,&h,&r);

	for(int i=1;i<=r;i++)
	{
		cin>>a[i].x>>a[i].y;
		if(a[i].x>a[i].y)
		{
			swap(a[i].x,a[i].y);
		}
	}
	sort(a+1,a+r+1,cmp);
	for(int i=1;i<=r;i++)
	{
		if(!(a[i].x==a[i+1].x&&a[i].y==a[i+1].y)||abs(a[i].x-a[i].y)<=1)
		{
			f[a[i].x+1]+=1;
			f[a[i].y]+=-1;
		}
	}
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		sum=sum+f[i];
		cout<<h-sum<<endl;
	}
			
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rem_Inory/article/details/81260925
今日推荐