该题一开始我用multiset写了一发,写的比较裸,TLE了 。 后来队友想到了一个比较好的方法 :将两个结构体排序之后,从大到小枚举Alice的h,对于每个h,将Bob中满足h小于当前h的牌的w加进multiset,然后用二分函数查找一下大于等于当前w的第一个数,当前迭代器的上一个指针就是小于当前w的最大w,找到就删除。那么也就是我们用了这样的贪心策略:对于Alice的每一张牌,要覆盖一张Bob的尽可能h和w接近它的牌 。 为什么这样的贪心策略是正确的呢 ? 假如不这样,那么当前牌会覆盖一张w更小的牌,假如之后的牌中有w比当前牌小,那么这样是不划算的,
如果有牌的w比当前牌大,那么显然也不可能更优 。
细节参见代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<list> #include<cmath> #include<set> #include<queue> using namespace std; typedef long long ll; const long long maxn = 100000+5; int T,n,m; struct node{ int h,w; bool operator < (const node& rhs) const { return h < rhs.h || (h == rhs.h && w < rhs.w); } }a[maxn],b[maxn]; multiset<int> g; int main() { scanf("%d",&T); while(T--){ g.clear(); scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i].h,&a[i].w); for(int i=0;i<n;i++) scanf("%d%d",&b[i].h,&b[i].w); sort(a,a+n); sort(b,b+n); int cur = 0,cnt=0; for(int i=0;i<n;i++){ while(cur<n&&b[cur].h<=a[i].h) g.insert(b[cur++].w); if(g.size()==0) continue; multiset<int> ::iterator it = g.lower_bound(a[i].w); if(it!=g.begin()) it--; if(*it<=a[i].w) g.erase(it),cnt++; } printf("%d\n",cnt); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-12-28 19:11:32