洛谷 1937 [USACO10MAR]仓配置Barn Allocation

【题解】

  贪心。 把区间按照右端点从小到大排序,右端点相同的按照长度从小到大排序,然后按顺序考虑,能放就放下去。 维护能不能放下去用线段树即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 #define rg register
 6 #define N 100010
 7 #define ls (u<<1)
 8 #define rs (u<<1|1)
 9 using namespace std;
10 int n,m,ans,mn[N<<2],del[N<<2];
11 struct seg{
12     int l,r;
13 }a[N];
14 inline int read(){
15     int k=0,f=1; char c=getchar();
16     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
17     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
18     return k*f;
19 }
20 void build(int u,int l,int r){
21     if(l<r){
22         int mid=(l+r)>>1;
23         build(ls,l,mid),build(rs,mid+1,r),mn[u]=min(mn[ls],mn[rs]);
24     }
25     else mn[u]=read();
26 }
27 inline void pushdown(int u){
28     mn[ls]+=del[u]; del[ls]+=del[u];
29     mn[rs]+=del[u]; del[rs]+=del[u];
30     del[u]=0;
31 }
32 void update(int u,int l,int r,int ul,int ur){
33     if(ul<=l&&r<=ur){
34         mn[u]--; del[u]-=1;
35         return;
36     }
37     int mid=(l+r)>>1; pushdown(u);
38     if(ul<=mid) update(ls,l,mid,ul,ur);
39     if(ur>mid) update(rs,mid+1,r,ul,ur);
40     mn[u]=min(mn[ls],mn[rs]);
41 }
42 int query(int u,int l,int r,int ul,int ur){
43     if(ul<=l&&r<=ur) return mn[u];
44     int mid=(l+r)>>1,ret=2e9; pushdown(u);
45     if(ul<=mid) ret=min(ret,query(ls,l,mid,ul,ur));
46     if(ur>mid) ret=min(ret,query(rs,mid+1,r,ul,ur));
47     return ret;
48 }
49 inline bool cmp(seg a,seg b){
50     if(a.r==b.r) return a.l>b.l;
51     return a.r<b.r;
52 }
53 int main(){
54     n=read(); m=read(); build(1,1,n);
55     for(rg int i=1;i<=m;i++) a[i].l=read(),a[i].r=read();
56     sort(a+1,a+1+m,cmp);
57     for(rg int i=1;i<=m;i++){
58         int tmp=query(1,1,n,a[i].l,a[i].r);
59         if(tmp>0){
60             ans++;
61             update(1,1,n,a[i].l,a[i].r);
62         }
63     }
64     printf("%d\n",ans);
65     return 0;
66 }

猜你喜欢

转载自www.cnblogs.com/DriverLao/p/9746556.html