zoukankan      html  css  js  c++  java
  • [USACO16FEB]负载平衡Load Balancing_Silver(NlogNlogN解法)

    这道题其实有两个版本(usaco两个组)

    较难版本的数据量应该是N<=1e5的

    这意味着这道题一定有NlogN或时间复杂度接近的解法。

    不难想到(模考的时候没想到),我们可以暴力枚举第一刀的情况然后二分第二刀的情况。因为如果只切一刀的时候,二分答案的正确性显然。那么我们切两刀的时候,枚举第一刀,然后第二刀就可以二分答案了。这就相当于一条扫描线。每向前推进一格,将这一条的所有点放入已扫描区域,从未扫描区域删除这些点。显然,我们可以用能维护区间的数据结构来实现。这里我选择了树状数组,读者也可以尝试用线段树。

    第一次做的时候,认为要开一个二维树状数组,然后发现,只需要维护一维的就够了,因为我们二分的时候是在一维上二分的。这里可以离散化一下但是洛谷的数据太水了我懒得离散化(雾

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100001
    int m;
    int tree[2][N*10];
    struct node
    {
        int x,y;
    }e[N];
    inline void read(int &x)
    {
        x=0;int f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
    }
    bool cmp(node p,node q)
    {
        return p.x<q.x;
    }
    inline int lowbit(int i)
    {
        return i&(-i);
    }
    void add(int t,int x,int w)
    {
        while(x<=m)
        {
            tree[t][x]+=w;
            x+=lowbit(x);
        }
    }
    int query(int t,int x)
    {
        int sum=0;
        while(x)
        {
            sum+=tree[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;
    }
    View Code
  • 相关阅读:
    堆排序算法的原理和实现
    图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
    图的迪杰斯特拉算法求最短路径
    第13章 切换到混合流并添加API访问
    第12章 添加对外部认证的支持
    第11章 使用OpenID Connect添加用户身份验证
    第10章 使用密码保护API
    第9章 使用客户端凭据保护API
    第8章 概述
    第7章 贡献
  • 原文地址:https://www.cnblogs.com/sherrlock/p/9812848.html
Copyright © 2011-2022 走看看