• 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;
    }
  • 相关阅读:
    致虚极守静笃
    DNS 透明代理
    Java“禁止”泛型数组
    Java和C#语法对比
    JVM 内存区域 (运行时数据区域)
    Java8 使用
    G1收集器的收集原理
    BZOJ 2222: [Cqoi2006]猜数游戏【神奇的做法,傻逼题,猜结论】
    数据结构之网络流入门(Network Flow)简单小节
    BZOJ 1257: [CQOI2007]余数之和sum【神奇的做法,思维题】
  • 原文地址:https://www.cnblogs.com/Zinn/p/9373266.html
Copyright © 2020-2023  润新知