同步賽上我一開始想了個看似正確卻漏洞百出的貪心:按\(a_i+b_i\)的和從大向小貪心
隨便想一想發現是假的,而後就寫了個28pts的暴力dp
杜神後半程說這題就是個貪心,但我沒時間寫了 (實際是沒想明白)
咱們來講這道題的正解:
咱們先珂以知足和最大,再知足並集大小大於等於\(l\)。因此咱們先將\(a\)序列和\(b\)序列排序,取出兩個序列的前\(k\)大
若是並集大小大於等於\(l\)就直接統計答案
不然咱們要湊滿\(l\)個都包含的,在湊的過程當中動態更新答案
咱們在兩個序列中都選中前\(k-l\)個不含有並集的數,並加入答案中,易知這些數必定含在答案中(這個珂以在草稿紙上推一推)。接下來考慮如何湊並集元素,一次湊一組:
1.兩個都沒被選中的狀況下的最大值,並將它們選中
2.一個被選中的狀況下的最大值。假設\(a[rk[i]]\)選中了,但\(b[rk[i]]\)沒選中,咱們就要找到一個最小的j使得\(a[rk[j]]\)沒被選中,咱們就珂以選中\(b[rk[i]\)和\(a[rk[j]]\),使得a中不成對的仍是\(k-l\)個。a,b反之亦然
咱們求出一、2兩種狀況貢獻最大值並更新選中狀態(都用堆維護,具體細節見代碼),重複\(l\)次便可求出答案
注意:兩次2也許就會將兩個都沒選中的變成都選中,因此要及時舍掉不合法的
#include <bits/stdc++.h>
#define N 200005
#define ll long long
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register ll x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int T,n,k,l,a[N],b[N],ar[N],br[N],va[N],vb[N],vis[N];
ll ans;
inline bool cmpa(register int x,register int y)
{
return a[x]>a[y];
}
inline bool cmpb(register int x,register int y)
{
return b[x]>b[y];
}
struct node{
int pos,val;
inline bool operator < (const node &it) const {
return val<it.val;
}
};
inline bool chkmax(register int &a,register int b)
{
return a<b?a=b,1:0;
}
int main()
{
T=read();
while(T--)
{
n=read(),k=read(),l=read();
for(register int i=1;i<=n;++i)
a[i]=read(),ar[i]=i,va[i]=vb[i]=vis[i]=0;
for(register int i=1;i<=n;++i)
b[i]=read(),br[i]=i;
sort(ar+1,ar+1+n,cmpa);
sort(br+1,br+1+n,cmpb);
for(register int i=1;i<=k;++i)
va[ar[i]]=1,vb[br[i]]=1;
ans=0;
priority_queue<int> pa,pb;
priority_queue<node> qa,qb;
for(register int i=1;i<=n;++i)
if(va[i]&&vb[i])
qb.push((node){i,a[i]+b[i]}),vis[i]=1;
if(qb.size()>=l)
{
for(register int i=1;i<=n;++i)
{
if(va[i])
ans+=a[i];
if(vb[i])
ans+=b[i];
}
}
else
{
for(register int i=1,tot=0;i<=k;++i)
if(!vb[ar[i]])
{
if(tot<k-l)
ans+=a[ar[i]],vis[ar[i]]=1,pa.push(b[ar[i]]);
else
qa.push((node){ar[i],a[ar[i]]+b[ar[i]]});
++tot;
}
for(register int i=1,tot=0;i<=n;++i)
if(!va[br[i]])
{
if(tot<k-l)
ans+=b[br[i]],vis[br[i]]=1,pb.push(a[br[i]]);
else
qb.push((node){br[i],a[br[i]]+b[br[i]]});
++tot;
}
int af=1,bf=1;
while(l--)
{
while(af<=k&&vis[ar[af]])
++af;
while(bf<=k&&vis[br[bf]])
++bf;
while(!qa.empty()&&vis[qa.top().pos]&&!(va[qa.top().pos]&&vb[qa.top().pos]))
qa.pop();
while(!qb.empty()&&vis[qb.top().pos]&&!(va[qb.top().pos]&&vb[qb.top().pos]))
qb.pop();
int maxx=0,typ=-1;
if(!qa.empty())
maxx=qa.top().val,typ=0;
if(!qb.empty()&&chkmax(maxx,qb.top().val))
typ=1;
if(!pa.empty()&&af<=k&&chkmax(maxx,pa.top()+a[ar[af]]))
typ=2;
if(!pb.empty()&&bf<=k&&chkmax(maxx,pb.top()+b[br[bf]]))
typ=3;
ans+=maxx;
if(typ==0)
vis[qa.top().pos]=1,qa.pop();
else if(typ==1)
vis[qb.top().pos]=1,qb.pop();
else if(typ==2)
vis[ar[af]]=1,pa.pop(),pa.push(b[ar[af]]);
else
vis[br[bf]]=1,pb.pop(),pb.push(a[br[bf]]);
}
}
write(ans),puts("");
}
return 0;
}