zoukankan      html  css  js  c++  java
  • 2151: 种树

    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.
    View Code
  • 相关阅读:
    C程序之修改Windows的控制台大小
    C程序之修改Windows的控制台颜色(转载)
    VS2010/MFC编程(对话框:模态对话框及其弹出过程)
    C/C++常用头文件及函数汇总
    vs2010点调试,显示系统找不到指定的文件
    C++之类和对象的使用(三)
    C++之类和对象的使用(二)
    idea激活方式
    Java之dom4j的简单解析和生成xml的应用
    Java之POI的excel导入导出
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3714655.html
Copyright © 2011-2022 走看看