贪心,STL,multiset(Alice and Bob,HDU 4268)

来源:互联网 发布:怎么看电脑mac地址 编辑:程序博客网 时间:2024/06/05 14:11

只想出了O(n^2)的算法。。。

A按宽升序排序。

B按高降序排序。

n^2循环,找到就{ans++;break;}。

超时。。

后来想用二分查找的,但没有抓住问题的本质,被二维的关系搞懵逼了,总把宽和高绑定在一起思考,很混乱。

想到上述方法也纯属抖机灵,没有想想为什么可以这样。

事实上应该解决一维后就放弃这一维,只考虑第二维。

上述方法的本质是从宽最小的开始找对手,找到能覆盖的对手中的最高的。

因为覆盖要同时宽覆盖与高覆盖,若宽最小的卡都能覆盖某对手,那么其他卡的也一定能宽覆盖这个对手(因此在宽上不用考虑它抢了队友的菜,反正大家都能覆盖,谁覆盖都一样,还不如派你这个最菜的先上,不亏),但不一定能高覆盖(其他卡在高的能力上不一定有你强,若你随便挑了一个不高的对手,那么有些本该被消灭的高的对手可能以后就无人能敌了)。先上最窄的是为了能在后续找对手中不用考虑宽。找到最高的对手是为了不抢队友的菜(你抢了队友的菜,队友又攻不下你的菜,就亏了)。

因此用多重集合进行二分查找时就只用把能宽覆盖的对手的高放进去而不需要将宽和高绑定后再扔进去了。将A,B按宽升序排序,由于从宽最小的开始找,那么随着宽增大,能宽覆盖的对手也是只增不减(被消灭的不算。。),因此每考虑一张新的卡,就多塞一些对手到集合里就OK了。由于对手也是升序,所以让他们排着队一波一波进集合就OK了。

时间复杂度O(nlogn)。


有一点很操蛋。。我用 it=upper_bound(s.begin(),s.end(),A[i].h);就超时。而且超时好多。。。

改为 it=s.upper_bound(A[i].h);就过了。。。

也不知道为什么。。。


代码

#include<stdio.h>#include<set>#include<algorithm>#define maxn 112345using namespace std;struct card{    int w,h;    bool operator < (const card& rhs) const    {        if(w!=rhs.w) return w<rhs.w;        else return h<rhs.h;    }}A[maxn],B[maxn];int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        for(int i=0;i<n;i++) scanf("%d %d",&A[i].w,&A[i].h);        for(int i=0;i<n;i++) scanf("%d %d",&B[i].w,&B[i].h);        sort(A,A+n);        sort(B,B+n);        multiset<int>s;        int k=0,ans=0;        for(int i=0;i<n;i++)        {            while(k<n&&B[k].w<=A[i].w) s.insert(B[k++].h);            if(s.empty()) continue;            multiset<int>::iterator it=s.upper_bound(A[i].h);            if(it!=s.begin())            {                ans++;                s.erase(--it);            }        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击