zoukankan      html  css  js  c++  java
  • BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

    BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

    Description

    Input

    第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数C_i * 第N+2到N+M+1行: 第i+N+1行表示2个整数 A_i和B_i

    Output

    * 第一行: 一个整数表示最多能够被满足的要求数

    Sample Input

    5 4
    1
    3
    2
    1
    3
    1 3
    2 5
    2 3
    4 5

    Sample Output

    3
     

    分析:把每头牛按右端点升序排序,然后能插就插,我们需要维护一下这段区间剩余空间的最小值,如果最小值大于0说明能放进去。
    这个我们用线段树来维护。
    贪心的证明则比较麻烦,我们需要考虑两个右端点不同的线段的几种可能的覆盖情况。
    能够发现一个事情,就是右端点小的那个  要么  能更好的利用所需的区间,要么 {右端点小的放不进去则右端点大的那个也放不进去。}
    所以我们不妨让右端点小的那个先试试。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    #define ls p<<1
    #define rs p<<1|1
    int t[N<<2],n,m,add[N<<2];
    struct C{
        int l,r;
    }a[N];
    bool cmp(const C &x,const C &y){if(x.r==y.r)return x.l>y.l;return x.r<y.r; }
    void build(int l,int r,int p)
    {
        if(l==r){
            scanf("%d",&t[p]);
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,ls);build(mid+1,r,rs);
        t[p]=min(t[ls],t[rs]);
    }
    void pushdown(int p)
    {
        int d=add[p];
        if(d)
        {
            t[ls]+=d;add[ls]+=d;
            t[rs]+=d;add[rs]+=d;
            add[p]=0;
        }
    }
    void update(int l,int r,int x,int y,int c,int p)
    {
        if(x<=l&&y>=r){
            t[p]+=c;
            add[p]+=c;
            return;
        }
        int mid=l+r>>1;
        pushdown(p);
        if(x<=mid) update(l,mid,x,y,c,ls);
        if(y>mid) update(mid+1,r,x,y,c,rs);
        t[p]=min(t[ls],t[rs]);
    }
    int query(int l,int r,int x,int y,int p)
    {
        if(x<=l&&y>=r) return t[p];
        int re=1<<30;
        pushdown(p);
        int mid=l+r>>1;
        if(x<=mid) re=min(re,query(l,mid,x,y,ls));
        if(y>mid) re=min(re,query(mid+1,r,x,y,rs));
        t[p]=min(t[ls],t[rs]);
        return re;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int i;
        memset(t,0x3f,sizeof(t));
        build(1,n,1);
        for(i=1;i<=m;i++) scanf("%d%d",&a[i].l,&a[i].r);
        sort(a+1,a+m+1,cmp);
        int ans=0;
        for(i=1;i<=m;i++)
        {
            int tmp=query(1,n,a[i].l,a[i].r,1);
            if(tmp>0){
                ans++;
                update(1,n,a[i].l,a[i].r,-1,1);
            }
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    《敏捷开发修炼之道》学习笔记3:交付用户想要的软件
    Photoshop快捷键大集合
    如何制作已编译的HTML帮助文件(即CHM帮助文件)
    根本不存在 DIV + CSS 布局这回事
    可将视频转换成Gif动画的相关软件
    SEO是什么?与spam有什么区别呢?
    视频六大编辑软件大比拼
    陈彤:一个网络编辑的11年
    最近出现的p2psvr.exe恶意程序的解决办法
    使用火狐浏览器Firefox的一些小技巧
  • 原文地址:https://www.cnblogs.com/suika/p/8711400.html
Copyright © 2011-2022 走看看