2151: 种树 - BZOJ
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不取)
然后构费用流的图(有点奇葩......)
然后跑费用流就行了
但是显然不能跑费用流,承受不了
所以我们模拟费用流
假设我们选了点2(因为费用最大),然后增广后,残留网络是这样的
第1,2,3条路都没了
但是我们可以走从1到2到3,即多了一条路,费用为a[1]+a[3]-a[2]
我们也可以分析出只多出了这条路,其他的路都是没有用的
因为a[2]>=a[1],所以我们不可能从1走到2再走到S,所以没有别的路了
所以对于这种情况我们就用a[pre[i]]+a[next[i]]-a[i]代替a[i],然后删除pre[i]和next[i]
还有一种情况就是i是两端
这种情况想一想就知道了,端点是最大的那么就选端点,然后删掉在端点的那两个值就行了
所以我们用堆维护最大值,做m次就行了
1 const 2 maxn=200010; 3 var 4 q,h,a,b,pre,next:array[0..maxn]of longint; 5 n,m,tot:longint; 6 7 function max(x,y:longint):longint; 8 begin 9 if x>y then exit(x); 10 exit(y); 11 end; 12 13 procedure swap(var x,y:longint); 14 var 15 t:longint; 16 begin 17 t:=x;x:=y;y:=t; 18 end; 19 20 procedure up(x:longint); 21 var 22 i:longint; 23 begin 24 while x>1 do 25 begin 26 i:=x>>1; 27 if b[q[x]]>b[q[i]] then 28 begin 29 swap(q[x],q[i]); 30 h[q[x]]:=x; 31 h[q[i]]:=i; 32 x:=i; 33 end 34 else break; 35 end; 36 end; 37 38 procedure down(x:longint); 39 var 40 i:longint; 41 begin 42 i:=x<<1; 43 while i<=tot do 44 begin 45 if (i<tot) and (b[q[i+1]]>b[q[i]]) then inc(i); 46 if b[q[i]]>b[q[x]] then 47 begin 48 swap(q[x],q[i]); 49 h[q[x]]:=x; 50 h[q[i]]:=i; 51 x:=i; 52 i:=x<<1; 53 end 54 else break; 55 end; 56 end; 57 58 procedure insert(x:longint); 59 begin 60 inc(tot); 61 h[x]:=tot; 62 q[tot]:=x; 63 up(tot); 64 end; 65 66 procedure delete(x:longint); 67 begin 68 if x=0 then exit; 69 b[q[x]]:=maxlongint; 70 up(x); 71 swap(q[1],q[tot]); 72 h[q[1]]:=1; 73 h[q[tot]]:=tot; 74 dec(tot); 75 down(1); 76 end; 77 78 function f(l,r:longint):longint; 79 var 80 i,u,v,t:longint; 81 begin 82 f:=0; 83 tot:=0; 84 for i:=l to r do 85 begin 86 b[i]:=a[i]; 87 insert(i); 88 pre[i]:=i-1; 89 next[i]:=i+1; 90 end; 91 pre[l]:=0; 92 next[r]:=0; 93 for i:=1 to m do 94 begin 95 t:=q[1]; 96 inc(f,b[t]); 97 u:=pre[t]; 98 v:=next[t]; 99 if (u<>0) and (v<>0) then 100 begin 101 b[t]:=b[u]+b[v]-b[t]; 102 pre[t]:=pre[u]; 103 next[t]:=next[v]; 104 next[pre[t]]:=t; 105 pre[next[t]]:=t; 106 down(h[t]); 107 end 108 else 109 begin 110 if u<>0 then next[pre[u]]:=0; 111 if v<>0 then pre[next[v]]:=0; 112 delete(h[t]); 113 end; 114 delete(h[u]); 115 delete(h[v]); 116 end; 117 end; 118 119 procedure main; 120 var 121 i:longint; 122 begin 123 read(n,m); 124 if m*2>n then 125 begin 126 writeln('Error!'); 127 exit; 128 end; 129 for i:=1 to n do 130 read(a[i]); 131 writeln(max(f(1,n-1),f(2,n))); 132 end; 133 134 begin 135 main; 136 end.