1. 程式人生 > 其它 >2021.7.21 義烏模擬賽 T1 A

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();
}