【题目】
题目描述:
智者奥尔曼曾说过:有缘的人即使相隔海角天涯,也会在梦境中相遇。
IcePrince_1968 和 IcePrincess_1968 便是如此。有一天 IcePrincess_1968 突发奇想:为什么不用梦境操控仪器来增加她和 IcePrince_1968 的缘分呢?
IcePrincess_1968 的梦境可以用 个区间来表示,第 个区间 表示她的第 个梦境会在 时刻开始,在 时刻结束(包含 和 两个时刻)。因为 IcePrincess_1968 经常做白日梦,所以 可能很大。
两个人的梦境不是什么时候都能融合的。只有在一些关键的与另一个人相关的梦境转折点两个人的梦境相遇,才能完成融合,形成浪漫的梦境。IcePrincess_1968 探测到 IcePrince_1968 近期的 个与 IcePrincess_1968 相关的梦境转折点,第 个转折点 表示他的第 个梦境转折点会在 时刻出现。因为 IcePrince_1968 和 IcePrincess_1968 很有缘,IcePrince_1968 经常梦到 IcePrincess_1968,所以 可能会很大。
当 IcePrincess_1968 的一个梦境包含了 IcePrince_1968 的一个梦境转折点时,两个人的这两段梦境就能得到融合。但要注意 IcePrincess_1968 的每段梦境只能和 IcePrince_1968 的一个梦境转折点融合,类似的,IcePrince_1968 的每个梦境转折点只能和 IcePrincess_1968 的一段梦境融合,否则会引发时空混乱。
IcePrincess_1968 很喜欢做和 IcePrince_1968 相关的梦。所以她想算出她的这些梦境最多能和 IcePrince_1968 的梦境转折点融合出多少个浪漫的梦境。但是 IcePrincess_1968 擅长文学但不擅长计算机,所以只能找你帮忙。
输入格式:
文件的第一行为有两个正整数 ,表示 IcePrincess_1968 的梦境个数和 IcePrince_1968 的与 IcePrincess_1968 相关的梦境转折点个数。
第 至第 行,每行两个正整数 ,第 行的两个数刻画了 IcePrincess_1968 的第 段梦境,含义如题面中所述。
第 至第 行,每行一个正数 ,第 行的两个数刻画了 IcePrince_1968 的第 个梦境转折点,含义如题面中所述。
输出格式:
输出文件仅一行,一个非负整数表示 IcePrincess_1968 最多能获得多少段浪漫的梦境。
样例数据:
输入
2 2
1 3
2 4
1
3
输出
2
提示:
【输入输出样例 1 解释】
IcePrincess_1968 可以将自己的第一段梦境和第一个梦境转折点匹配,第二段梦境和第二个梦境转折点匹配,从而获得两段浪漫的梦境。因为 IcePrincess_1968 一共只做了两个梦,所以这一定是最多的数量。
【数据范围】
对于 的数据, , ;
对于 的数据, , ;
对于 的数据, , ;
对于 的数据, , , , 。
【分析】
这是一道贪心啊,考试的时候打了 分网络流暴力就没管了。。。
我们将梦境转折点从小到大排序,依次为每个梦境转折点安排梦境。
对于一个梦境转折点,最优的选法就是选包含它的区间中右端点离它最近的区间。如果没有区间包含它或包含它的区间已被选,跳过这个店就可以了。
正确性比较显然,这里不给出证明,可以自己画图理解一下。
然后可以用离散化 优先队列来优化这一过程,就可以通过这道题啦。
时间复杂度
【代码】
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 800005
#define inf ((1ll<<31)-1)
using namespace std;
int n,m,k,sum=0,Max=0;
int l[N],r[N],t[N],d[N],S[N];
vector<int>right[N];
priority_queue<int>q;
void discrete()
{
sort(d+1,d+sum+1);
k=unique(d+1,d+sum+1)-(d+1);
for(int i=1;i<=n;++i)
{
l[i]=lower_bound(d+1,d+k+1,l[i])-d;
r[i]=lower_bound(d+1,d+k+1,r[i])-d;
right[l[i]].push_back(r[i]),Max=max(Max,r[i]);
}
for(int i=1;i<=m;++i)
t[i]=lower_bound(d+1,d+k+1,t[i])-d,S[t[i]]++,Max=max(Max,t[i]);
}
int main()
{
int x,i,j,ans=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
{
scanf("%d%d",&l[i],&r[i]);
d[++sum]=l[i],d[++sum]=r[i];
}
for(i=1;i<=m;++i)
scanf("%d",&t[i]),d[++sum]=t[i];
discrete();
for(i=1;i<=Max;++i)
{
for(j=right[i].size()-1;j>=0;--j) q.push(-right[i][j]);
while(S[i]--)
{
while(!q.empty()&&(-q.top())<i) q.pop();
if(!q.empty()) ans++,q.pop();
}
}
printf("%d",ans);
return 0;
}