「luogu3415」 祭坛
离散化,二分答案,扫描y轴,用树状数组统计个数即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int n,cntx[N],cnty[N],ans1,ans2; 5 vector<int>px[N],py[N]; 6 struct P{ 7 int data,pos; 8 bool operator<(const P& k)const{return data<k.data;}; 9 }x[N],y[N]; 10 vector<P>s,t; 11 int totx,toty,a[N],b[N],bit[N]; 12 inline int lowbit(int k){return k&(-k);} 13 inline void add(int pos,int x){while(pos<=toty) bit[pos]+=x,pos+=lowbit(pos);return;} 14 inline int que(int k){ 15 int ans=0; 16 while(k) ans+=bit[k],k-=lowbit(k); 17 return ans; 18 } 19 int check(int k){ 20 int spos,tpos,tots,tott,ans=0,ii=0,jj=0; 21 s.clear();t.clear(); 22 memset(bit,0,sizeof(bit)); 23 for(int i=1;i<=totx;i++){ 24 spos=k-1,tpos=cntx[i]-k; 25 if(spos>=tpos) continue; 26 s.push_back((P){px[i][spos]+1,i});t.push_back((P){px[i][tpos],i}); 27 } 28 sort(s.begin(),s.end());sort(t.begin(),t.end()); 29 tots=s.size(),tott=t.size(); 30 for(int i=1;i<=toty;i++){ 31 while(ii<tots&&s[ii].data==i) add(s[ii++].pos,1); 32 while(jj<tott&&t[jj].data==i) add(t[jj++].pos,-1); 33 spos=k-1,tpos=cnty[i]-k; 34 if(spos>=tpos) continue; 35 ans+=que(py[i][tpos]-1)-que(py[i][spos]); 36 } 37 return ans; 38 } 39 int main(){ 40 scanf("%d",&n); 41 for(int i=1;i<=n;i++) scanf("%d%d",&x[i].data,&y[i].data),x[i].pos=y[i].pos=i; 42 sort(x+1,x+n+1);sort(y+1,y+n+1); 43 x[0].data=y[0].data=-1; 44 for(int i=1;i<=n;i++){ 45 if(x[i].data!=x[i-1].data) totx++; 46 if(y[i].data!=y[i-1].data) toty++; 47 a[x[i].pos]=totx,b[y[i].pos]=toty; 48 } 49 for(int i=1;i<=n;i++){ 50 px[a[i]].push_back(b[i]); 51 py[b[i]].push_back(a[i]); 52 } 53 for(int i=1;i<=totx;i++){ 54 cntx[i]=px[i].size(),cnty[i]=py[i].size(); 55 if(cntx[i]>=2)sort(px[i].begin(),px[i].end()); 56 if(cnty[i]>=2) sort(py[i].begin(),py[i].end()); 57 } 58 int l=1,r=n/4; 59 while(l<=r){ 60 int mid=(l+r)>>1; 61 int temp=check(mid); 62 if(temp) ans1=mid,ans2=temp,l=mid+1; 63 else r=mid-1; 64 } 65 printf("%d\n%d",ans1,ans2); 66 return 0; 67 }