[CSP-S模拟测试]:赛(贪心+三分)

题目描述

由于出题人思维枯竭所以想不出好玩的背景。
有$n$个物品,第$i$个物品的价格是$v_i$,有两个人,每个人都喜欢$n$个物品中的一些物品。
要求选出正好$m$个物品,满足选出的物品中至少有$k$个物品被第一个人喜欢,$k$个物品被第二个人喜欢。并求出最小的价格和。


输入格式

第一行三个数$n,m,k$。
第二行$n$个数,第$i$个数表示$v_i$。
第三行包含一个数$a$,表示第一个人喜欢的物品数。
第四行包含$a$个数,表示第一个人喜欢的物品是哪几个。
第五行包含一个数$b$,表示第二个人喜欢的物品数。
第六行包含$b$个数,表示第二个人喜欢的物品是哪几个。


输出格式

一个数表示答案。若不存在合法的方案则输出$-1$。


样例

样例输入:

4 3 2
3 2 2 1
2
1 2
2
1 3

样例输出:

7


数据范围与提示

对于测试点$1\sim 4$:$n\leqslant 20$。
对于测试点$5\sim 10$:不存在一个物品被两个人喜欢。
对于测试点$11\sim 15$:$n\leqslant 2\times 10^3$。
对于测试点$16\sim 20$:无特殊限制。
对于所有的数据,$n\leqslant 2\times 10^5,m,k\leqslant n,v_i\leqslant 10^9$。


题解

这道题优秀的随机化可以拿到$95$分……

我们可以设两个人喜欢的物品交集个数为$r$,那么我们就可以贪心了。

发现答案满足单谷,于是我们可以三分。

其实三分也是存在漏洞的,因为一段的$r$可能对应一样的答案,但是显然随机数据没有卡。

时间复杂度:$\Theta(n\log k)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include
using namespace std;
int N,M,K,A,B;
int v[200001];
bool a[200001],b[200001];
int que[4][200001],top1,top2,top3,top4;
long long ans=1LL<<60;
bool cmp(int x,int y){return v[x]M){puts("-1");return 0;}
	sort(que[0]+1,que[0]+top1+1,cmp);
	sort(que[1]+1,que[1]+top2+1,cmp);
	sort(que[2]+1,que[2]+top3+1,cmp);
	sort(que[3]+1,que[3]+top4+1,cmp);
	v[0]=0x3f3f3f3f;
	int lft=max(K-min(top2,top3),max(2*K-M,0));
	int rht=min(K,top4);
	while(rht-lft>2)
	{
		int midl=lft+(rht-lft)/3;
		int midr=rht-(rht-lft)/3;
		if(judge(midl)

rp++

你可能感兴趣的:([CSP-S模拟测试]:赛(贪心+三分))