【bzoj1828/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
 

网上的题解基本都是贪心+线段树,不过有种更加好写的写法→v→
先把每段区间按照左端点从小到大排序,并且对于原区间的差分数组l++,r+1--。
最开始ans=m;
从小到大枚举畜栏,那么now加上当前位置差分的值就是这个点被多少区间覆盖。
再把以这个点为左端点的区间的右端点放入大根堆中。
如果发现此畜栏的容纳量小于当前区间数,就从大根堆里取出now-a[i]个右端点,并且把右端点+1的地方差分数组++(相当于放弃这个区间),ans--。
 

代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 const int N=1e5+10;
 6 int n,m,a[N],p[N];
 7 struct node{int l,r;}e[N];
 8 bool cmp(node aa,node bb){return aa.l<bb.l;}
 9 int read(){
10     int ans=0,f=1;char c=getchar();
11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
12     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
13     return ans*f;
14 }
15 std::priority_queue<int>q;
16 int main(){
17     n=read();m=read();
18     for(int i=1;i<=n;i++)a[i]=read();
19     for(int i=1;i<=m;i++){
20         int l=read(),r=read();e[i]=(node){l,r};
21         p[l]++;p[r+1]--;
22     }
23     std::sort(e+1,e+1+m,cmp);
24     int now=0,h=1;int ans=m;
25     for(int i=1;i<=n;i++){
26         now+=p[i];
27         while(h<=m&&e[h].l==i)q.push(e[h].r),h++;
28         while(now>a[i]&&!q.empty()){
29             int pp=q.top();q.pop();
30             p[pp+1]++;now--;ans--;
31         }
32     }
33     printf("%d\n",ans);
34     return 0;
35 }
36 
bzoj1828

 

posted @ 2017-10-13 19:49  Child-Single  阅读(158)  评论(0编辑  收藏  举报