Description
Input
Output
Sample Input
5 10
1 1
2 2
3 3
4 4
5 5
Sample Output
4
Data Constraint
Hint
Solution
首先,每个点的横纵坐标相互独立,所以可以分开来做。 先考虑一个 n log^2 n 的做法: 二分答案 ans,将前 1~ans 个数排序,然后对于第 i 个数 x,它的贡献是 i*x-sum[i],sum[i] 表示排序后前 i 个数的和。 注意到这个做法的时间浪费在 log n 次排序上,而排序的时间复杂度是 n log n 的。 我们可以一开始先将 n 个点进行 n log n 的排序,然后再 O(N)算出每个数的排名,这样在二分 答案中的排序就可以做到 O(N)。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int n; 5 long long d,s[1000000],ss[1000000]; 6 struct arr 7 { 8 int z,w; 9 }x[1000000],y[1000000]; 10 bool cmp(arr x,arr y) 11 { 12 return x.z<y.z; 13 } 14 bool pd(int xx) 15 { 16 int t=0; 17 for (int i=1;i<=n;i++) 18 if (x[i].w<=xx) 19 s[++t]=x[i].z; 20 long long sum=0; 21 for (int i=1;i<=xx;i++) 22 { 23 sum+=s[i]*(i-1)-ss[i-1]; 24 ss[i]=ss[i-1]+s[i]; 25 } 26 t=0; 27 for (int i=1;i<=n;i++) 28 if (y[i].w<=xx) 29 s[++t]=y[i].z; 30 for (int i=1;i<=xx;i++) 31 { 32 sum+=s[i]*(i-1)-ss[i-1]; 33 ss[i]=ss[i-1]+s[i]; 34 } 35 if (sum<=d) return true; 36 else return false; 37 } 38 int main() 39 { 40 scanf("%d%lld",&n,&d); 41 for (int i=1;i<=n;i++) 42 { 43 scanf("%lld%lld",&x[i].z,&y[i].z); 44 x[i].w=y[i].w=i; 45 } 46 sort(x+1,x+n+1,cmp); 47 sort(y+1,y+n+1,cmp); 48 int l=1,r=n; 49 while (l<r) 50 { 51 int mid=(l+r)/2; 52 if (pd(mid)) 53 l=mid+1; 54 else r=mid; 55 } 56 if (l==n&&pd(l)) 57 printf("-1"); 58 else printf("%d",l); 59 }