做法:横纵显然互不影响,先思考二分答案后,我们对前ans个点排序,每个点贡献为i*x-sum[i],sum[i]为前缀和,可这样会超时,而复杂度主要来自排序,
所以我们考虑先排序,然后记录排名,每次二分答案后就可以用小学生排序。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define N 600007 5 #define LL long long 6 #define rep(i,a,b) for(int i=a;i<=b;i++) 7 #include <algorithm> 8 using namespace std; 9 int n; 10 LL d, Qx[N], Qy[N],Sumx[N],Sumy[N]; 11 struct arr{ 12 LL val; 13 int site; 14 }a[N],b[N]; 15 16 int Cmp(arr x,arr y){ 17 return x.val<y.val; 18 } 19 20 bool Check(int ain){ 21 LL sum=0; 22 rep(i,1,n){ 23 if(a[i].site<=ain) Qx[++Qx[0]]=a[i].val; 24 if(b[i].site<=ain) Qy[++Qy[0]]=b[i].val; 25 } 26 rep(i,1,ain){ 27 Sumx[i]=Sumx[i-1]+Qx[i]; 28 sum+=Qx[i]*i-Sumx[i]; 29 Sumy[i]=Sumy[i-1]+Qy[i]; 30 sum+=Qy[i]*i-Sumy[i]; 31 } 32 Qx[0]=Qy[0]=0; 33 rep(i,1,ain){ 34 Qx[i]=Qy[i]=0; 35 Sumx[i]=Sumy[i]=0; 36 } 37 if(sum>=d) return 1; else return 0; 38 } 39 40 void Work(){ 41 int l=1,r=n; 42 for(;l<r;){ 43 int mid=(l+r)/2; 44 if(Check(mid)) r=mid; else l=mid+1; 45 } 46 if(l!=n) printf("%d",l); 47 else printf("-1"); 48 } 49 50 int main(){ 51 scanf("%d%lld",&n,&d); 52 rep(i,1,n) 53 scanf("%lld%lld", &a[i].val,&b[i].val),a[i].site=i,b[i].site=i; 54 sort(a+1,a+n+1,Cmp); 55 sort(b+1,b+n+1,Cmp); 56 Work(); 57 }