您的位置:首页 > 其它

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

2013-10-15 21:49 447 查看


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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: