bzoj千题计划180:bzoj4411: [Usaco2016 Feb]Load balancing
http://www.lydsy.com/JudgeOnline/problem.php?id=4411
用树状数组维护扫描线
一个树状数组维护扫描线之上的y<=i点,另一个维护扫描线之下y<=i的点
将点按x排好序,开始全部插入扫描线之下的树状数组
枚举x这一条线,线上的在第一个树状数组里加上,第二个树状数组里减去
最大值是一个单峰函数
可以用二分或三分
二分的话,哪边大往哪边移
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 #define lowbit(x) x&-x int m; int c[2][N*10]; struct node { int x,y; }e[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool cmp(node p,node q) { return p.x<q.x; } void add(int t,int x,int w) { while(x<=m) { c[t][x]+=w; x+=lowbit(x); } } int query(int t,int x) { int sum=0; while(x) { sum+=c[t][x]; x-=lowbit(x); } return sum; } int main() { int n; read(n); for(int i=1;i<=n;++i) { read(e[i].x); read(e[i].y); m=max(m,e[i].y); } for(int i=1;i<=n;++i) add(1,e[i].y,1); sort(e+1,e+n+1,cmp); int j; int ans=n; int l,r,mid,tmp; int sum0,sum1,tot0,tot1; for(int i=1;i<=n;i=j) { j=i; while(j<=n && e[j].x==e[i].x) { add(1,e[j].y,-1); add(0,e[j].y,1); j++; } l=1; r=m; tot0=query(0,m); tot1=query(1,m); tmp=1; while(l<=r) { mid=l+r>>1; sum0=query(0,mid); sum1=query(1,mid); if(max(sum0,sum1)>=max(tot0-sum0,tot1-sum1)) { tmp=mid; r=mid-1; } else l=mid+1; } sum0=query(0,tmp); sum1=query(1,tmp); ans=min(ans,max(max(sum0,sum1),max(tot0-sum0,tot1-sum1))); } cout<<ans; }