给你一个矩阵,里面有些点,让你横向切一刀,纵向切一刀,使得得到的四个区域内的最大的点数最少。
7
7 3
5 5
7 13
3 1
11 7
5 3
9 1
2
#include
#include
#include
using namespace std;
const int INF = 0xfffffff;
const int maxn = 500000 + 10;
const int maxm = 100000 + 10;
int srchq[maxn], prex[maxn], prey[maxn], left, right, down, up, n, cnt, ok, x, y;
bool exist[maxn];
//struct poi{
// int x, y;
//}point[maxm];
vector<int> which[maxn];
int node[4 * maxn];
void Insert(int l, int r, int now, int aim){
node[now] ++;
if(l == r)
return;
int m = (l + r) / 2;
if(aim > m)
Insert(m + 1, r, now * 2 + 1, aim);
else
Insert(l, m, now * 2, aim);
}
void Query(int al, int ar, int l, int r, int now){
int m = (l + r) / 2;
if(al <= l && ar >= r)
ok += node[now];
else{
if(al <= m)
Query(al, ar, l, m, now * 2);
if(ar > m)
Query(al, ar, m + 1, r, now * 2 + 1);
}
}
void Readin(){
left = down = INF;
right = up = -INF;
scanf("%d", &n);
for(int i = 1; i <= n; i ++){
scanf("%d %d", &x, &y);
left = min(left, (x + 1) / 2);
right = max(right, (x + 1) / 2);
down = min(down, (y + 1) / 2);
up = max(up, (y + 1) / 2);
prex[(x + 1) / 2] ++;
prey[(y + 1) / 2] ++;
if(!exist[(y + 1) / 2]){
exist[(y + 1) / 2] = 1;
srchq[++ cnt] = (y + 1) / 2;
}
which[(y + 1) / 2].push_back((x + 1) / 2);
}
}
void Calcpre(){
for(int i = left; i <= right; i ++)
prex[i] += prex[i - 1];
for(int i = down; i <= up; i ++)
prey[i] += prey[i - 1];
}
void Init(){
scanf("%d", &n);
left = down = INF;
right = up = -INF;
Readin();
Calcpre();
}
//int Calcpoint(int right, int up){
// int tmp = 0;
// for(int i = 1; i <= n; i ++)
// if(point[i].x < right && point[i].y < up)
// tmp ++;
// return tmp;
//}
//int Three(int i){
// int l = left, r = right, brk1, brk2, ans1, ans2, tmp;
// while(l < r){
// brk1 = l + (r - l) / 3;
// brk2 = r - (r - l) / 3;
// tmp = Calcpoint(brk1, i);
// ans1 = max(prey[i] - tmp, max(prex[brk1] - tmp, max(tmp, n - (prey[i] + prex[brk1] - tmp))));
// tmp = Calcpoint(brk2, i);
// ans2 = max(prey[i] - tmp, max(prex[brk2] - tmp, max(tmp, n - (prey[i] + prex[brk2] - tmp))));
// if(ans1 < ans2)
// r = brk2 - 1;
// else
// l = brk1 + 1;
// }
// return r;
//}
//void Solve(){
// int ans = INF;
// for(int i = down + 1; i < up; i += 2)
// ans = min(ans, Three(i));
// printf("%d", ans);
//}
//int Calcpoint(int right, int up){
// int tmp = 0;
// for(int i = 1; i <= n; i ++)
// if(point[i].x < right * 2 && point[i].y < up * 2)
// tmp ++;
// return tmp;
//}
//int Three(int i){
// int l = left, r = right, brk1, brk2, ans1, ans2, tmp;
// while(l < r){
// brk1 = l + (r - l) / 3;
// brk2 = r - (r - l) / 3;
// tmp = Calcpoint(brk1, i);
// ans1 = max(max(max(n - (prex[brk1] + prey[i] - tmp), prex[brk1] - tmp), tmp), prey[i] - tmp);
// tmp = Calcpoint(brk2, i);
// ans2 = max(max(max(n - (prex[brk2] + prey[i] - tmp), prex[brk2] - tmp), tmp), prey[i] - tmp);
// if(ans1 < ans2)
// r = brk2 - 1;
// else
// l = brk1 + 1;
// }
// tmp = Calcpoint(r, i);
// return max(max(max(n - (prex[r] + prey[i] - tmp), prex[r] - tmp), tmp), prey[i] - tmp);
//}
int Two(int i){
int lmax, rmax, l = left, r = right - 1, m, tmp;
while(l < r){
m = (l + r) / 2;
// tmp = Calcpoint(m, i);
ok = 0;
Query(left - 1, m, left - 1, right, 1);
tmp = ok;
lmax = max(tmp, prex[m] - tmp);
rmax = max(prey[i] - tmp, n - (prex[m] + prey[i] - tmp));
if(lmax < rmax)
l = m + 1;
else
if(lmax == rmax){
r = m;
break;
}
else
r = m - 1;
}
ok = 0;
Query(left - 1, r, left - 1, right, 1);
tmp = ok;
lmax = max(tmp, prex[r] - tmp);
rmax = max(prey[i] - tmp, n - (prex[r] + prey[i] - tmp));
return max(lmax, rmax);
}
void Solve(){
int ans = INF;
sort(srchq + 1, srchq + cnt + 1);
// for(int i = down; i <= up; i ++)
for(int i = 1; i <= cnt - 1; i ++){
for(int j = 0; j < which[srchq[i]].size(); j ++)
Insert(left - 1, right, 1, which[srchq[i]][j]);
// ans = min(ans, Three(srchq[i]));
ans = min(ans, Two(srchq[i]));
}
printf("%d", ans);
}
int main(){
freopen("balancing.in", "r", stdin);
freopen("balancing.out", "w", stdout);
Readin();
Calcpre();
Solve();
return 0;
}