比赛 20170912 评测结果 AAAAAAAAAA
题目名称 平凡的题面 最终得分 100
用户昵称 Mayuri 运行时间 0.247 s
代码语言 C++ 内存使用 2.61 MiB
提交时间 2017-09-12 19:50:25
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))

const int maxN=100101;
const int inf=2147483647;

class Rang//区间or点
{
public:
	int l,r;
	int style;//0表示是区间,1表示是点
};

bool operator < (Rang A,Rang B)
{
	if (A.l!=B.l)//保证左端点小的在前面,这样可以保证某个点被处理时能覆盖其的区间都在其前面
		return A.l<B.l;
	return A.style<B.style;//保证区间在点之前被处理
}

int n,m;
Rang R[maxN*2];
priority_queue<int,vector<int>,greater<int> > Q;//优先队列,小的优先

int read();

int main()
{
	freopen("bg.in","r",stdin);
	freopen("bg.out","w",stdout);
	n=read();
	m=read();
	for (int i=1;i<=n;i++)
	{
		int u=read();
		R[i].l=u;
		R[i].style=1;
	}
	for (int i=1;i<=m;i++)
	{
		int l=read(),r=read();
		R[i+n].l=l;
		R[i+n].r=r;
		R[i+n].style=0;
	}
	sort(&R[1],&R[n+m+1]);
	int Ans=0;
	for (int i=1;i<=n+m;i++)
	{
		if (R[i].style==0)//如果是区间,则直接放入优先队列
			Q.push(R[i].r);//因为已经保证左端点单调,所以只需要放入右端点
		else//如果是点,则说明能覆盖其的区间都在优先队列中了,查找是否存在这样的区间,并找出右端点最小的(贪心原理)
		{
			while ((!Q.empty())&&(Q.top()<R[i].l))//弹出所有冗余区间,因为排过序,所以可以保证如果此时这个区间是冗余的,后面也一定是冗余的
				Q.pop();
			if (!Q.empty())//因为有可能不存在,即此时队列为空,所以只有队列不为空时才说明存在能覆盖的
			{
				Ans++;
				Q.pop();//注意弹掉这个区间,因为其已经覆盖
			}
		}
	}
	cout<<Ans<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

int read()
{
	int x=0;
	int k=1;
	char ch=getchar();
	while (((ch>'9')||(ch<'0'))&&(ch!='-'))
		ch=getchar();
	if (ch=='-')
	{
		k=-1;
		ch=getchar();
	}
	while ((ch>='0')&&(ch<='9'))
	{
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*k;
}