[贪心][Usaco2010 Mar]balloc 农场分配

来源:互联网 发布:qt多进程编程 编辑:程序博客网 时间:2024/05/21 08:33


solution:

我们将所有区间按照左端点排序后,从右往左,能添加则添加不能就不添加,这样贪心是正确的。因为我们可以维护两个性质:

1.最大性

2.方案对后面的区间一定是最优的。证明略。

能这么做的原因是因为这道题是无权的。

假如区间有权的话,那么等价于选出K条路径,路径上每个区间不相交且权值最大,可以用费用流做。


#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int M=100010;int n,m,res,x,y;int t[M<<2],s[M<<2];struct Node{int u,v;friend bool operator <(const Node a,const Node b){if(a.u==b.u)return a.v<b.v;else return a.u<b.u;}}a[M];void build(int o,int l,int r){if(l==r){scanf("%d",&t[o]);return;}int M=l+r>>1;build(o<<1,l,M);build(o<<1|1,M+1,r);t[o]=min(t[o<<1],t[o<<1|1]);}inline void pushdown(int o){if(s[o]){int l=o<<1;int r=l+1;s[l]+=s[o];s[r]+=s[o];t[l]-=s[o];t[r]-=s[o];s[o]=0;}}int ask(int o,int l,int r){if(x<=l && y>=r)return t[o];pushdown(o);int M=l+r>>1,ans=M;if(x<=M)ans=min(ans,ask(o<<1,l,M));if(y>M)ans=min(ans,ask(o<<1|1,M+1,r));return ans;}void update(int o,int l,int r){if(x<=l && y>=r){t[o]--;s[o]++;return;}pushdown(o);int M=l+r>>1;if(x<=M)update(o<<1,l,M);if(y>M)update(o<<1|1,M+1,r);t[o]=min(t[o<<1],t[o<<1|1]);}int main(){scanf("%d %d",&n,&m);build(1,1,n);for(int i=1;i<=m;++i)scanf("%d %d",&a[i].u,&a[i].v);sort(a+1,a+1+m);for(int i=m;i>=1;--i){x=a[i].u;y=a[i].v;if(ask(1,1,n)<1)continue;res++;update(1,1,n);}printf("%d\n",res);return 0;}


原创粉丝点击