Jzoj4737 金色丝线将瞬间一分为二(GOSICK系列)

继续上一篇那套题


可以将x,y宙分开讨论,对于每一维维护一个数据结构求出所有比之小的部分的和和比之大的部分的和

所以我们先将这些点分别按x,y轴排序,得到rankx和ranky之后用树状数组即可

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define LL long long
#define N 600010
#define mid (l+r>>1)
using namespace std;
int x[N],y[N],r1[N],r2[N],n,v[N]; LL b,c,S=0,d; 
struct Seg{
	LL s[N]; int c[N];
	void insert(int x,int k){ for(;x<=n;x+=x&-x) s[x]+=k,++c[x]; }
	LL sum(int x,LL& C,LL S=0){ for(;x;x^=x&-x) S+=s[x],C+=c[x]; return S; }
	LL query(int l,int r,LL& cnt){
		LL c1,S=sum(r,cnt)-sum(l-1,c1); cnt-=c1; return S;
	}
} s1,s2;
inline bool c1(int a,int b){ return x[a]<x[b]; }
inline bool c2(int a,int b){ return y[a]<y[b]; }
int main(){ 
	scanf("%d%lld",&n,&d);
	for(int i=1;i<=n;++i){
		r1[i]=r2[i]=i;
		scanf("%d%d",x+i,y+i);
	}
	sort(r1+1,r1+1+n,c1);
	sort(r2+1,r2+1+n,c2);
	for(int i=1;i<=n;++i) v[r1[i]]=i; memcpy(r1,v,sizeof v);
	for(int i=1;i<=n;++i) v[r2[i]]=i; memcpy(r2,v,sizeof v);
	for(int i=1;i<=n;++i){
		c=0; b=s1.query(1,r1[i],c); S+=c*x[i]-b;
		c=0; b=s1.query(r1[i],n,c); S+=b-c*x[i];
		c=0; b=s2.query(1,r2[i],c); S+=c*y[i]-b;
		c=0; b=s2.query(r2[i],n,c); S+=b-c*y[i];
		if(S>d) return 0&printf("%d
",i);
		s1.insert(r1[i],x[i]); s2.insert(r2[i],y[i]);
	}
	puts("-1");
}

原文地址:https://www.cnblogs.com/Extended-Ash/p/9477293.html