[贪心][优先队列] Jzoj P6275 梦境
题解
- 我们先根据区间的左端点从小到大排序,将转折点也从小到大排序
- 然后我们加入以r为关键字的小根堆,然后就贪心
- 找到包含转折点的区间右端点离转折点最近的区间弹出,因为右端点越远,越有可能对后面的转折点提供贡献
- 注意要把右端点比转折点还小的区间弹出
代码
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #define N 200010 7 using namespace std; 8 struct node 9 { 10 int l,r; 11 bool operator <(const node &a) const { return r>a.r; } 12 }a[N]; 13 priority_queue<node>Q; 14 int n,m,j=1,ans,d[N]; 15 bool cmp(node a,node b) { return a.l==b.l?a.r<b.r:a.l<b.l; } 16 int main() 17 { 18 freopen("dream.in","r",stdin),freopen("dream.out","w",stdout),scanf("%d%d",&n,&m); 19 for (int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r); 20 for (int i=1;i<=m;i++) scanf("%d",&d[i]); 21 sort(a+1,a+n+1,cmp),sort(d+1,d+m+1); 22 for (int i=1;i<=m;i++) 23 { 24 while (j<=n&&a[j].l<=d[i]) Q.push(a[j++]); 25 while (!Q.empty()&&Q.top().r<d[i]) Q.pop(); 26 if (!Q.empty()) ans++,Q.pop(); 27 } 28 printf("%d",ans); 29 }