Problem: [Usaco2016 Feb]Load Balancing
Time Limit: 1 Sec Memory Limit: 128 MB
Description
农民约翰的N只牛分别站在他的二维农场的不同位置(x1,y1)…(xn,yn)(1<=N<=100,xi和yi是正整奇数,最大值
是B)。他想建一排无限长度的南北方向的满足等式x=a的围栏来把他的农场分成两部分(a是一个偶数,确保了不
会使围栏建在任何一只牛的位置上)。他也想建一个无限长度的东西方向的满足等式y=b的围栏(b也是偶数)。这
两个围栏在(a,b)点相交,并把农场分成了四个区域。约翰想选一对a和b使四个区域是"平衡"的,即不要让一个
区域包含太多的牛。令M为四个区域中牛的数量的最大值,约翰想使M尽量的小。请帮他求出最小的M。对于前5组数
据,B保证最大为100。在所有数据中,B保证最大为1,000,000。
Input
第一行包含两个整数N和B。接下来的N行每行包含一只牛的位置x和y
Output
输出M的最小值
Sample Input
7 10
7 3
5 5
9 7
3 1
7 7
5 3
9 1
Sample Output
2
代码如下
#include<bits/stdc++.h>
using namespace std;
int n,m,pos[100050],sum[100050],now;
int c[100050],ans,l,r,tl,tr,tot;
struct node {
int x,y,tmp;
bool operator<(const node & p)const {
return x==p.x? tmp<p.tmp:x<p.x;
}
} num[100050];
bool cmp(int a,int b) {
return num[a].tmp<num[b].tmp;
}
void calc_push(int u) {
while(u<=now) {
++c[u];
u+=u&-u;
}
}
int calc_ask(int u) {
int cnt=0;
while(u) {
cnt+=c[u];
u-=u&-u;
}
return cnt;
}
int check(int u) {
int tmp=calc_ask(u);
int ent=max(max(tmp,tot-1-tmp),max(sum[u]-tmp,n-(sum[u]-tmp+tot-1)));
ans=min(ans,ent);
return ent;
}
void calc() {
l=1,r=now;
while(l<r) {
tl=((l<<1)+r)/3;
tr=(l+(r<<1))/3;
if(l==tl) ++tl;
if(r==tr) --tr;
if(check(tl)<check(tr)) r=tr;
else l=tl;
}
}
int main() {
scanf("%d",&n);
scanf("%d",&ans);
ans=n;
for(int i=1; i<=n; ++i) {
scanf("%d%d",&num[i].x,&num[i].tmp);
pos[i]=i;
}
sort(num+1,num+n+1);
sort(pos+1,pos+n+1,cmp);
for(int i=1; i<=n; ++i) {
if(num[pos[i]].tmp!=num[pos[i-1]].tmp) {
ans=min(ans,max(sum[now],n-sum[now]));
sum[now+1]=sum[now];
++now;
}
num[pos[i]].y=now;
++sum[now];
}
for(int i=1; i<=n; i=tot) {
tot=i;
while(num[tot].x==num[i].x)
calc_push(num[tot++].y);
calc();
}
printf("%d",ans);
return 0;
}