[bzoj4411] [Usaco2016 Feb]Load balancing
先离散化一下(也可以不用
枚举横坐标,用线段树维护两边纵坐标上的节点数。
每次在线段树上二分。。。(感觉似乎树状数组也行?
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100233; 7 const int mxnode=262233; 8 struct poi{ 9 int x,y; 10 }a[maxn]; 11 struct yy{ 12 int y,id; 13 }y[maxn];int cnty; 14 int sz[2][mxnode],lnum[2],rnum[2]; 15 int i,j,k,n,m,ans,size; 16 17 int ra;char rx; 18 inline int read(){ 19 rx=getchar(),ra=0; 20 while(rx<'0'||rx>'9')rx=getchar(); 21 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 22 } 23 bool cmpy(yy a,yy b){return a.y<b.y;} 24 bool cmppoi(poi a,poi b){return a.x<b.x;} 25 inline int min(int a,int b){return a<b?a:b;} 26 inline int max(int a,int b){return a>b?a:b;} 27 inline int query(){ 28 int p=1,lc,rc;bool flag=0; 29 lnum[0]=lnum[1]=rnum[0]=rnum[1]=0; 30 while(1){ 31 lc=p<<1,rc=lc|1; 32 if(p>size)lc=rc=p,flag=1; 33 if(max(lnum[0]+sz[0][lc],lnum[1]+sz[1][lc]) < max(rnum[0]+sz[0][rc],rnum[1]+sz[1][rc])) 34 lnum[0]+=sz[0][lc],lnum[1]+=sz[1][lc],p=rc; 35 else rnum[0]+=sz[0][rc],rnum[1]+=sz[1][rc],p=lc; 36 //printf(" %d %d %d %d %d\n",lnum[0],lnum[1],rnum[0],rnum[1],p); 37 if(flag) 38 return max(max(lnum[0],lnum[1]),max(rnum[0],rnum[1])); 39 } 40 41 } 42 int main(){ 43 n=read(); 44 for(i=1;i<=n;i++)a[i].x=read(),a[i].y=y[i].y=read(),y[i].id=i; 45 sort(y+1,y+1+n,cmpy); 46 for(i=1;i<=n;i++) 47 cnty+=y[i].y!=y[i-1].y,a[y[i].id].y=cnty; 48 for(size=1;size<cnty;size<<=1);size--;//printf(" %d\n",size); 49 sort(a+1,a+1+n,cmppoi); 50 51 for(i=1;i<=n;i++) 52 ++sz[1][a[i].y+size]; 53 for(i=size;i;i--)sz[1][i]=sz[1][i<<1]+sz[1][i<<1|1]; 54 55 int now=1;ans=query(); 56 for(i=1;i<=n;i++)if(a[i].x!=a[i+1].x) 57 { 58 // printf("try:%d\n",a[i].x); 59 for(;now<=i;now++) 60 for(j=a[now].y+size;j;j>>=1)++sz[0][j],--sz[1][j]; 61 ans=min(ans,query()); 62 } 63 printf("%d\n",ans); 64 return 0; 65 }