2021.7.21 义乌模拟赛 T1 A
这个东西正着不太好做我们考虑二分转化成判定性问题。
然后问题就变成:每个物品有一个重量和一个容量,要选取最多的物品且选取一个物品时已经选的物品重量总和不能超过当前物品容积。
这个东西可以反悔贪心,具体地,我们维护一个堆,并将\(B\)排序,然后得到一个物品时先判断能不能直接放进去,然后看能不能将最大的替换出来即可。
时间复杂度\(O(nlog^2n)\)似乎吊打std的\(O(nmlogn)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 100000
#define M 20000
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,k,l,r,mid,T;ll Sum;
struct ques{int A,B;}S[N+5];I bool cmp(ques x,ques y){return (x.B==y.B)?(x.A<y.A):(x.B<y.B);}priority_queue<int> Q;
I int check(int mid){
re int i,j=1;Sum=0;while(!Q.empty()) Q.pop();for(i=1;i<=n;i++){
if(Sum+mid<=S[i].B-S[i].A) Sum+=S[i].A,Q.push(S[i].A);
else if(!Q.empty()&&S[i].A<Q.top()) Sum+=S[i].A-Q.top(),Q.pop(),Q.push(S[i].A);
}return Q.size()>=m+1;
}
I void Solve(){
re int i;scanf("%d%d",&n,&m);l=0;r=0;for(i=1;i<=n;i++)scanf("%d%d",&S[i].A,&S[i].B),r=max(r,S[i].B);r++;sort(S+1,S+n+1,cmp);
while(l+1<r) mid=l+r>>1,(check(mid)?l:r)=mid;printf("%d\n",l);
}
int main(){
freopen("a.in","r",stdin);freopen("a.out","w",stdout);
re int i;scanf("%d",&T);while(T--)Solve();
}