发现我根本做不动ahcisy做的题啊……
orz了一发ahcisy题解
首先把有一个抽屉里没有这种种类的都刨出去然后直接计算
那么考虑每种都是两个抽屉里都有的情况
最劣情况肯定是把所有种类分成两个集合,第一个集合里共有p个,第二个集合里共有q个,第一个抽屉里拿的就是这p个,第二个里拿的就是那q个
那么所有x<=p,y<=q的就都不合法
那么枚举2^n种分法,搞一发单调栈就行了
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 21
#define MAXM 1100010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct data{
int v[2];
friend bool operator <(data x,data y){
return x.v[0]!=y.v[0]?x.v[0]<y.v[0]:x.v[1]>y.v[1];
}
};
int n,tot;
int a[2][MAXN];
int ad[2];
data c[MAXM];
data st[MAXM];
int tp;
int ansv=2000000000,ans1=2000000000,ans2=2000000000;
void ud(int x,int y){
if(x+y<ansv||(x+y==ansv&&x<ans1)){
ansv=x+y;
ans1=x;
ans2=y;
}
}
int main(){
int i,j;
scanf("%d",&n);
for(i=0;i<2;i++){
for(j=0;j<n;j++){
scanf("%d",&a[i][j]);
}
}
for(i=0;i<n;i++){
if(!a[0][i]||!a[1][i]){
ad[0]+=a[0][i];
ad[1]+=a[1][i];
}else{
a[0][tot]=a[0][i];
a[1][tot++]=a[1][i];
}
}
n=tot;
int N=1<<n;
for(i=0;i<N;i++){
for(j=0;j<n;j++){
c[i].v[i>>j&1]+=a[i>>j&1][j];
}
}
ud(c[0].v[0],1);
ud(1,c[N-1].v[1]);
sort(c,c+N);
for(i=0;i<N;i++){
while(tp&&st[tp].v[1]<c[i].v[1]){
tp--;
}
st[++tp]=c[i];
}
for(i=2;i<=tp;i++){
ud(st[i-1].v[0]+1,st[i].v[1]+1);
}
printf("%d %d\n",ans1+ad[0],ans2+ad[1]);
return 0;
}
/*
*/