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;
}

 

posted @ 2018-01-02 14:26  TRTTG  阅读(329)  评论(0编辑  收藏  举报