您的位置:首页 > 其它

2151: 种树 - BZOJ

2014-05-07 21:24 567 查看
Description

A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
Input

输入的第一行包含两个正整数n、m。第二行n个整数Ai。
Output

输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
Sample Input
【样例输入1】
7 3
1 2 3 4 5 6 7
【样例输入2】
7 4
1 2 3 4 5 6 7

Sample Output
【样例输出1】
15

【样例输出2】
Error!
【数据规模】
对于全部数据:m<=n;
-1000<=Ai<=1000
N的大小对于不同数据有所不同:
数据编号 N的大小 数据编号 N的大小
1 30 11 200
2 35 12 2007
3 40 13 2008
4 45 14 2009
5 50 15 2010
6 55 16 2011
7 60 17 2012
8 65 18 199999
9 200 19 199999
10 200 20 200000

看wikioi的题解完全没有看懂

于是问了群里的人,结果告诉我是费用流优化

搞了半天总算懂了

首先我们把它拆成链,因为这样我们就好做了,我们只要算两遍就行了,一个是[1,n-1](表示n不取)一个是[2,n](表示1不取)

然后构费用流的图(有点奇葩......)

const
maxn=200010;
var
q,h,a,b,pre,next:array[0..maxn]of longint;
n,m,tot:longint;

function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end;

procedure swap(var x,y:longint);
var
t:longint;
begin
t:=x;x:=y;y:=t;
end;

procedure up(x:longint);
var
i:longint;
begin
while x>1 do
begin
i:=x>>1;
if b[q[x]]>b[q[i]] then
begin
swap(q[x],q[i]);
h[q[x]]:=x;
h[q[i]]:=i;
x:=i;
end
else break;
end;
end;

procedure down(x:longint);
var
i:longint;
begin
i:=x<<1;
while i<=tot do
begin
if (i<tot) and (b[q[i+1]]>b[q[i]]) then inc(i);
if b[q[i]]>b[q[x]] then
begin
swap(q[x],q[i]);
h[q[x]]:=x;
h[q[i]]:=i;
x:=i;
i:=x<<1;
end
else break;
end;
end;

procedure insert(x:longint);
begin
inc(tot);
h[x]:=tot;
q[tot]:=x;
up(tot);
end;

procedure delete(x:longint);
begin
if x=0 then exit;
b[q[x]]:=maxlongint;
up(x);
swap(q[1],q[tot]);
h[q[1]]:=1;
h[q[tot]]:=tot;
dec(tot);
down(1);
end;

function f(l,r:longint):longint;
var
i,u,v,t:longint;
begin
f:=0;
tot:=0;
for i:=l to r do
begin
b[i]:=a[i];
insert(i);
pre[i]:=i-1;
next[i]:=i+1;
end;
pre[l]:=0;
next[r]:=0;
for i:=1 to m do
begin
t:=q[1];
inc(f,b[t]);
u:=pre[t];
v:=next[t];
if (u<>0) and (v<>0) then
begin
b[t]:=b[u]+b[v]-b[t];
pre[t]:=pre[u];
next[t]:=next[v];
next[pre[t]]:=t;
pre[next[t]]:=t;
down(h[t]);
end
else
begin
if u<>0 then next[pre[u]]:=0;
if v<>0 then pre[next[v]]:=0;
delete(h[t]);
end;
delete(h[u]);
delete(h[v]);
end;
end;

procedure main;
var
i:longint;
begin
read(n,m);
if m*2>n then
begin
writeln('Error!');
exit;
end;
for i:=1 to n do
read(a[i]);
writeln(max(f(1,n-1),f(2,n)));
end;

begin
main;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: