http://acm.hdu.edu.cn/showproblem.php?pid=6563
要么用最大的卡去尝试攻击对面所有的攻击状态的卡
要么就尽量小的代价吧防御状态的都清空,然后剩下的就尝试攻击所有工作的卡,如果还有剩余就直接冲脸
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=1e5+10;
int n,m,cas;ll ans;
ll a[maxl],b[maxl];
vector<ll> atk,dfd;
bool vis[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),vis[i]=false;
for(int i=1;i<=m;i++)
scanf("%lld",&b[i]);
atk.clear();dfd.clear();
int x;
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
if(x)
dfd.push_back(b[i]);
else
atk.push_back(b[i]);
}
sort(a+1,a+1+n);
sort(atk.begin(),atk.end());
sort(dfd.begin(),dfd.end());
}
inline void mainwork()
{
ans=0;
ll tmp;int l1,l2,alen=atk.size(),dlen=dfd.size();
tmp=0;l1=max(1,n-alen+1);l2=1;
for(int i=0;i<alen;i++)
{
if(l1>n) break;
while(a[l1]<atk[i] && l1+1<=n)
l1++;
if(a[l1]<atk[i])
break;
tmp+=a[l1]-atk[i];
l1++;
}
ans=tmp;
tmp=0;l1=1;
for(int i=0;i<dlen;i++)
{
while(a[l1]<dfd[i] && l1+1<=n)
l1++;
if(a[l1]<dfd[i])
return;
vis[l1]=true;
++l1;
}
l1=1;bool flag=true;
for(int i=0;i<alen;i++)
{
if(l1>n) break;
while((a[l1]<atk[i] || vis[l1]) && l1+1<=n)
l1++;
if(vis[l1] || a[l1]<atk[i])
{
flag=false;
break;
}
tmp+=a[l1]-atk[i];
vis[l1]=true;
++l1;
}
if(flag)
{
for(int i=1;i<=n;i++)
if(!vis[i])
tmp+=a[i];
}
ans=max(tmp,ans);
}
inline void print()
{
printf("Case %d: %lld\n",cas,ans);
}
int main()
{
int t;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}