题解 P3661 【[USACO17FEB]Why Did the Cow Cross the Road I S】

StudyingFather

2019-08-19 17:13:34

Solution

先考虑一个朴素的贪心做法。 我们将 $ T_i $ 排序,对于每个 $ T_i $,将其与满足条件且右端点最靠左的区间进行匹配。 这样的复杂度是 $ O(nc) $ 的,~~听说有人过了~~,但这样的解法其实还有很大优化空间。 我们将区间按左端点为关键字排序,建立一个以右端点为关键字的小根堆。 对于每个 $ T_i $,我们将所有左端点小于 $ T_i $ 的区间插入堆(这些区间都将成为候选的可安排区间),接着将所有右端点小于 $ T_i $ 的区间从堆中弹出(因为 $ T_i $ 递增,未来这些区间也不可能被安排)。 执行完上面几步后,堆顶的区间正满足上面朴素做法中的“满足条件且右端点最靠左的区间”,可以与当前 $ T_i $ 匹配。 该算法的复杂度是 $ O(n \log n) $。 ```cpp #include <cstdio> #include <queue> #include <algorithm> using namespace std; struct seg { int l,r; bool operator<(const seg&a)const { return r>a.r; } }s[20005]; int a[20005],vis[20005]; priority_queue<seg> q; bool cmp(const seg&a,const seg&b) { return a.l<b.l; } int main() { int c,n; scanf("%d%d",&c,&n); for(int i=1;i<=c;i++) scanf("%d",&a[i]); sort(a+1,a+c+1); for(int i=1;i<=n;i++) scanf("%d%d",&s[i].l,&s[i].r); sort(s+1,s+n+1,cmp); int cur=1,ans=0; for(int i=1;i<=c;i++) { while(cur<=n&&s[cur].l<=a[i]) q.push(s[cur++]); while(!q.empty()&&q.top().r<a[i]) q.pop(); if(!q.empty())ans++,q.pop(); } printf("%d\n",ans); return 0; } ```