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