洛谷 P1937 仓配置

传送门:洛谷 P1937 仓配置
题目描述:

如图,牛栏里只能容纳一定空间,进行线段覆盖,且覆盖数不能超过空间,求最大线段数

畜栏号:      1   2   3   4   5
           +---+---+---+---+---+
容纳空间:   | 1 | 3 | 2 | 1 | 3 |  
           +---+---+---+---+---+
Cow 1      XXXXXXXXXXXXX            (1, 3)
Cow 2           XXXXXXXXXXXXXXXX    (2, 5)
Cow 3           XXXXXXXX            (2, 3)
Cow 4                   XXXXXXXX    (4, 5)

算法分析:考虑贪心:先让靠右的、占线段长度最小的入驻,这样就能避免覆盖中的重合问题。这样排序,然后用线段树维护当前区间剩余数量的最小值,若能入住 (\(query>0\)) 就将空间减少 (\(update\)) 即可


#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<algorithm>
#define rd int
#define in(x) x=read()
#define ls k<<1
#define rs k<<1 | 1
#define mid ((l+r)>>1)
#define maxN 100010
#define G ch=getchar()
#define lson ls,l,mid
#define rson rs,mid+1,r
#define f(x,y) for(register int i=x;i<=y;++i)
#define q(x,y) tree.query(1,1,n,x,y,0)
#define u(x,y) tree.update(1,1,n,x,y,-1),tot++
#define S a[i].s
#define T a[i].t
using namespace std;
inline rd read();
struct Query
{
    int s,t;
}a[maxN+1];
class segment_tree
{
    public:
        void build(int k,int l,int r)
        {
            if(l==r) {in(sum[k]); return;}
            build(lson); build(rson);
            pushup(k);
        }
        void update(int k,int l,int r,int ql,int qr,int w)
        {
            if(ql<=l && r<=qr) {sum[k]+=w; v[k]+=w; return;}
            if(v[k]) pushdown(k,l,r);
            if(ql<=mid) update(lson,ql,qr,w);
            if(qr>mid) update(rson,ql,qr,w);
            pushup(k);
        }
        int query(int k,int l,int r,int ql,int qr,int w)
        {
            if(ql<=l && r<=qr) return sum[k];
            int ans=INT_MAX;
            if(v[k]) pushdown(k,l,r);
            if(ql<=mid) ans=min(ans,query(lson,ql,qr,w));
            if(qr>mid) ans=min(ans,query(rson,ql,qr,w));
            return ans;
        }
    private:
        void pushup(int k) {sum[k]=min(sum[ls],sum[rs]);}
        void pushdown(int k,int l,int r)
        {
            v[ls]+=v[k]; v[rs]+=v[k];
            sum[ls]+=v[k]; sum[rs]+=v[k];
            v[k]=0;
        }
        int v[4*maxN+1],sum[4*maxN+1];
};
segment_tree tree;
void subtask();
int n,m,tot=0;
bool comp(Query x,Query y) {return (x.t!=y.t)?(x.t<y.t):(x.s>y.s);}
int main()
{
    subtask();
    return 0;
}
void subtask()
{
    in(n); in(m); tree.build(1,1,n);
    f(1,m) {in(a[i].s); in(a[i].t);}
    sort(a+1,a+m+1,comp);
    f(1,m) if(q(S,T)>0) u(S,T);
    printf("%d",tot);
}
inline rd read()
{
    rd num=0,f=1;
    char ch=getchar();
    while((ch<'0' || ch>'9') && ch!='-') G;
    if(ch=='-') {f=-1; G;}
    while(ch>='0' && ch<='9') {num=num*10+ch-'0'; G;}
    return num*f;
}
posted @ 2019-02-16 21:22  常青藤的花语  阅读(156)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。