bzoj 1034 [ ZJOI 2008 ] 泡泡堂BNB —— 贪心

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1034

一开始想了个很麻烦的贪心做法,对于每个 a[i],找第一个大于它的 b 匹配……

然后WA...因为这样好像没有利用不能第一次匹配的值使答案更优;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const maxn=1e5+5;
int n,a[maxn],b[maxn],mx,mn;
bool vis1[maxn];
priority_queue<int>q;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    sort(a+1,a+n+1); sort(b+1,b+n+1);
    int t=1;
    for(int i=1;i<=n;i++)
    {
        while(b[t]<=a[i]&&t<=n)q.push(b[t]),t++;
        if(t>n)break;
        vis1[i]=1; t++;
    }
    for(int i=1;i<=n;i++)
    {
        if(vis1[i])continue;
        int x=q.top(); q.pop();
        if(a[i]==x)mn++;
        else mn+=2;
    }
    memset(vis1,0,sizeof vis1); 
    while(q.size())q.pop();
    t=n;
    for(int i=n;i;i--)
    {
        while(b[t]>=a[i]&&t)q.push(-b[t]),t--;
        if(!t)break;
        vis1[i]=1; t--; mx+=2;
    }
    for(int i=n;i;i--)
    {
        if(vis1[i])continue;
        int x=-q.top(); q.pop();
        if(a[i]==x)mx++;
    }
    printf("%d %d",mx,mn);
    return 0;
}

优美的正解贪心不是全局考虑,而是每次考虑最大值和最小值;

如果最小值能盖过对方的最小值或最大值能盖过对方的最大值,就直接进行;

不行就用自己的最小值匹配对方的最大值,让答案最优。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+5;
int n,a[maxn],b[maxn];
int solve(int a[],int b[])
{
    int ans=0,l1=1,l2=1,r1=n,r2=n;
    while(l1<=r1&&l2<=r2)
    {
        if(a[l1]>b[l2])ans+=2,l1++,l2++;
        else if(a[r1]>b[r2])ans+=2,r1--,r2--;
        else ans+=(a[l1]==b[r2]),l1++,r2--;//
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    sort(a+1,a+n+1); sort(b+1,b+n+1);
    printf("%d %d",solve(a,b),2*n-solve(b,a));
    return 0;
}

 

posted @ 2018-07-26 17:40  Zinn  阅读(173)  评论(0编辑  收藏  举报