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; }