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