P2587 [ZJOI2008]泡泡堂
一看就是田忌赛马搞搞贪心
考虑如何求最优方案
$1$.考虑当前队伍最强的人,如果他比敌方最强的强,那么有于他一定会得两分,所以直接找到敌方最强的得到两分就好,也可以为后面减少压力
$2$.考虑一下当前队伍中最菜的人,如果他比对方队伍中最菜的强,那么就让他们比,得到两分,因为敌方最菜的一定会白给两分,直接用最菜的换掉就好,强的肯定要留到后面
$3$.如果当前队伍中最菜的人比对方最菜的还菜,那么由于他一定会白给两分,直接给敌方最强两分就行,为后面减少压力
$4.$如果当前队伍最菜的人和敌方最菜的一样菜,那么也和对方最强的换掉就好了,因为此时敌方最强的比队伍最强的还强(否则 $1$. 时就先打了),敌方最强一定会得到两分,如果我方最菜和敌方最菜打个平局,敌方最强的还是会得到两分,而如果换掉敌方最强的我们之后的人也可以把敌方最菜给干掉得到两分
所以己方的最优方案就是这样搞
发现总分总是 $2n$,如果敌方多了己方就少了,所以己方最劣方案就是敌方最优方案,同样求就行
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=4e5+7; int n,a[N],b[N],ans1,ans2; int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=read(); sort(a+1,a+n+1); sort(b+1,b+n+1); int ar=n,br=n,bl=1,al=1; while(al<=ar) { if(a[ar]>b[br]) { ans1+=2; ar--,br--; continue; } if(a[al]>b[bl]) { ans1+=2; al++,bl++; continue; } ans1+=(a[al]==b[br]); al++,br--; } ar=br=n; al=bl=1; while(bl<=br) { if(b[br]>a[ar]) { ans2+=2; br--,ar--; continue; } if(b[bl]>a[al]) { ans2+=2; bl++,al++; continue; } ans2+=(b[bl]==a[ar]); bl++,ar--; } printf("%d %d\n",ans1,2*n-ans2); return 0; }