Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值ai,以及一个大小bi
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述:
第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数ai,bi,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v
输出描述:
仅一行,代表最大的中位数
示例1
输入
20 5 3
3 5
5 6
8 7
10 6
15 10
输出
8
#include<bits/stdc++.h>
using namespace std;
typedef long long s64;
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)
#define gc (c=getchar())
int read()
{
char c;
while(gc<'0');
int x=c-'0';
while(gc>='0')x=x*10+c-'0';
return x;
}
const int N=5e6+5,U=1<<15;
int cnt[U];
int n,a[N],b[N],qa[N],qb[N];
int idb[N];
bool mark[N];
s64 s1[N],s2[N];
int q1[N];
void get(int q[],int a[])
{
rep(i,0,U-1)cnt[i]=0;
rep(i,1,n)++cnt[a[i]%U];
rep(i,1,U-1)cnt[i]+=cnt[i-1];
per(i,n,1)q1[cnt[a[i]%U]--]=i;
rep(i,0,U-1)cnt[i]=0;
rep(i,1,n)++cnt[a[i]/U];
rep(i,1,U-1)cnt[i]+=cnt[i-1];
per(i,n,1)q[cnt[a[q1[i]]/U]--]=q1[i];
}
s64 sum;int tail;
void del(int x)
{
mark[x]=1;
if(x<=tail)
{
sum-=b[qb[x]];
while(++tail,mark[tail]);
sum+=b[qb[tail]];
}
}
int k;
void init_s()
{
rep(i,1,n)idb[qb[i]]=i;
sum=0;
rep(i,1,k)sum+=b[qb[i]];
s64 sum0=sum;
tail=k;
s2[1]=sum;
rep(i,2,n-k+1)
{
del(idb[qa[i-1]]);
s2[i]=sum;
}
sum=sum0;tail=k;
rep(i,1,n)mark[i]=0;
s1[n]=sum;
per(i,n-1,k)
{
del(idb[qa[i+1]]);
s1[i]=sum;
}
}
int main()
{
//freopen("1.in","r",stdin);
int v=read();
n=read();
int m=read();
rep(i,1,n){a[i]=read();b[i]=read();}
get(qa,a);
get(qb,b);
k=m/2;
init_s();
if(m%2)
{
per(i,n-k,1)
if(s1[i-1]+b[qa[i]]+s2[i+1]<=v)
{
cout<<a[qa[i]];
break;
}
}
else
{
per(i,n-k,1)
if(s1[i]+s2[i+1]<=v)
{
cout<<(a[qa[i]]+a[qa[i+1]])/2;
break;
}
}
}