二分答案,但是这里的判断不同于一般的二分。

分别将cows和cowc按照s和c排序。

我的代码里check函数的返回值含义如下:

-1 直接输出,不可能满足条件了

0 这种方案是满足条件的,可以把中位数调大试试

1 这种方案是不满足的,但是把中位数调大就有可能满足了(否则不可能满足)

2 这种方案是不满足的,但是把中位数调小就有可能满足了(否则不可能满足)

还是不会用cpp,用了switch语句却没写break,导致纠结了好长时间。

终于给家里台式机装上Ubuntu了,才发现NOI Linux就是害人用的啊。

 

参考代码

# include <cstdio>
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxN=100005;
struct Node{ int c,s,id; };
int n,m,tot;
Node cows[maxN],cowc[maxN];

bool cmps(Node a,Node b) { return a.s<b.s; }
bool cmpc(Node a,Node b) { return a.c<b.c; }

int check(int limit)
{
	int left=0,right=0,all=cows[limit].c;
	for (int i=0;i<n;i++){
		if ((cowc[i].id<limit)&&(all+cowc[i].c<=tot)&&(left<m/2)){
			all+=cowc[i].c;left++;
		} else if ((cowc[i].id>limit)&&(all+cowc[i].c<=tot)&&(right<m/2)){
			all+=cowc[i].c;right++;
		}
	}
	if ((left<m/2)&&(right<m/2)) return -1;
	else if (left<m/2) return 1;
	else if (right<m/2) return 2;
	else return 0;
}

int main()
{
	scanf("%d%d%d",&m,&n,&tot);
	for (int i=0;i<n;i++) scanf("%d%d",&cows[i].s,&cows[i].c);
	sort(cows,cows+n,cmps);
	for (int i=0;i<n;i++) cows[i].id=i;
	memcpy(cowc,cows,sizeof(cows));
	sort(cowc,cowc+n,cmpc);
	int l=1,r=n,ans=-1;
	while (l<=r){
		int mid=(l+r)>>1;
		switch (check(mid)){
			case -1: { printf("-1\n"); return 0; }
			case  0: { ans=cows[mid].s; l=mid+1; break; }
			case  1: { l=mid+1; break;}
			case  2: { r=mid-1; }
		}
	}
	if (ans>=0) printf("%d\n",ans); else printf("-1\n");
	return 0;
}