5 10
1 1
2 2
3 3
4 4
5 5
4
这里写图片描述
首先,我们考虑n log^2 n的做法。
不难发现,x和y可以分开单独处理
二分答案ans,把1到ans的元素排序,然后查询每一个数对答案的贡献。
现在我们要减少一个log
发现二分时并不需要每次排序。
我们可以事先给整个序列排序,则可以得到所有数字的排名。
二分时直接O(n)桶排即可。
%:pragma GCC optimize(3)
#include
#include
#include
#include
using namespace std;
const int maxn=6e5+77;
long long x[maxn],y[maxn],d,ans=0,a[maxn],s[maxn],b[maxn];
int n,d1[maxn],d2[maxn];
bool cmpx(int a,int b) { return x[a]bool cmpy(int a,int b) { return y[a]int main()
{
scanf("%d%lld",&n,&d);
for(int i=1; i<=n; i++)
{
scanf("%lld%lld",&x[i],&y[i]);
d1[i]=d2[i]=i;
}
sort(d1+1,d1+n+1,cmpx); sort(d2+1,d2+n+1,cmpy);
// for(int i=1; i<=n; i++) printf("x[d1[%d]]=%d\n",i,x[d1[i]]);
int l=1,r=n+1;
while(l<=r)
{
int mid=(l+r)>>1; ans=0;
memset(a,-1,sizeof(a));
for(int i=1; i<=n; i++) if(d1[i]<=mid) a[i]=x[d1[i]];
int t=0;
for(int i=1; i<=n; i++) if(a[i]>=0)
s[++t]=s[t-1]+a[i],b[t]=a[i];
for(int i=1; i<=mid; i++) ans+=i*b[i]-s[i];
memset(a,-1,sizeof(a));
for(int i=1; i<=n; i++) if(d2[i]<=mid) a[i]=y[d2[i]];
t=0;
for(int i=1; i<=n; i++) if(a[i]>=0) s[++t]=s[t-1]+a[i],b[t]=a[i];
for(int i=1; i<=mid; i++) ans+=i*b[i]-s[i];
if(ans>=d) r=mid-1;else l=mid+1;
}
printf("%d",r==n+1?-1:l);
}