• bzoj2436


    不难发现两边的活动是交替进行的,我们可以dp

    先对时间离散化,设f[i,j]到时间i一个会场选j个活动,另一个会场最多有多少活动,那么f[i,j]=max(f[k,j]+s[k,i],f[k,j-s[k,i]])

    然后第一问的答案就是max(min(f[n*2,i],i))

    第二问是要求必选一个,那这一定形如中间一段必须选,向左向右分别dp

    假设中间那段是(i,j)时最优值是g[i,j]

    肯定要预处理时间i前一个会场选j个活动,另一个会场最多有多少活动和时间i到结束一个会场选j个活动,另一个会场最多有多少活动

    我们记为fl[i,j],fr[i,j],不难得到g[i,j]=max{min(x+y+s[i,j],fl[i,x]+fr[j,y])} (注意到f[]数组的两个会场取值是对称的)

    处理g[i,j]是O(n4)的,拍几组数据可以发现当i,j固定时,随着x的增大,对应最优的y减小

    其实主观上也很好理解,肯定是两个会场活动尽量平衡,证明吗……不会……

      1 var fl,fr,f,g:array[0..410,0..410] of longint;
      2     a,s,e:array[0..410] of longint;
      3     i,n,m,k,j,x,y,ans,t:longint;
      4 
      5 procedure max(var a:longint; b:longint);
      6   begin
      7     if a<b then a:=b;
      8   end;
      9 
     10 function min(a,b:longint):longint;
     11   begin
     12     if a>b then exit(b) else exit(a);
     13   end;
     14 
     15 procedure swap(var a,b:longint);
     16   var c:longint;
     17   begin
     18     c:=a;
     19     a:=b;
     20     b:=c;
     21   end;
     22 
     23 procedure sort(l,r:longint);
     24   var i,j,x:longint;
     25   begin
     26     i:=l;
     27     j:=r;
     28     x:=a[(l+r) shr 1];
     29     repeat
     30       while a[i]<x do inc(i);
     31       while x<a[j] do dec(j);
     32       if not(i>j) then
     33       begin
     34         swap(a[i],a[j]);
     35         inc(i);
     36         dec(j);
     37       end;
     38     until i>j;
     39     if l<j then sort(l,j);
     40     if i<r then sort(i,r);
     41   end;
     42 
     43 function find(l,r,x:longint):longint;
     44   var m:longint;
     45   begin
     46     while l<=r do
     47     begin
     48       m:=(l+r) shr 1;
     49       if a[m]=x then exit(m);
     50       if a[m]>x then r:=m-1 else l:=m+1;
     51     end;
     52   end;
     53 
     54 begin
     55   readln(n);
     56   for i:=1 to n do
     57   begin
     58     readln(s[i],e[i]);
     59     e[i]:=s[i]+e[i];
     60     inc(t);
     61     a[t]:=s[i];
     62     inc(t);
     63     a[t]:=e[i];
     64   end;
     65   sort(1,t);
     66   m:=1;
     67   for i:=2 to t do
     68     if a[i]<>a[m] then
     69     begin
     70       inc(m);
     71       a[m]:=a[i];
     72     end;
     73   for i:=1 to n do
     74   begin
     75     s[i]:=find(1,m,s[i]);
     76     e[i]:=find(1,m,e[i]);
     77     inc(g[s[i],e[i]]);
     78   end;
     79   for i:=1 to m do
     80     for j:=i+1 to m do
     81       inc(g[i,j],g[i,j-1]);
     82   for j:=1 to m do
     83     for i:=j-1 downto 1 do
     84       inc(g[i,j],g[i+1,j]);
     85   for i:=0 to m+1 do
     86     for j:=0 to n do
     87     begin
     88       fl[i,j]:=-n;
     89       fr[i,j]:=-n;
     90     end;
     91   fl[0,0]:=0; fr[m+1,0]:=0;
     92   for i:=1 to m do
     93     for j:=0 to i-1 do
     94       for k:=0 to n do
     95       begin
     96         max(fl[i,k],fl[j,k]+g[j,i]);
     97         if k>=g[j,i] then max(fl[i,k],fl[j,k-g[j,i]]);
     98       end;
     99   for i:=m downto 1 do
    100     for j:=i+1 to m+1 do
    101       for k:=0 to n do
    102       begin
    103         max(fr[i,k],fr[j,k]+g[i,j]);
    104         if k>=g[i,j] then max(fr[i,k],fr[j,k-g[i,j]]);
    105       end;
    106   ans:=0;
    107   for i:=0 to n do
    108     max(ans,min(fl[m,i],i));
    109   writeln(ans);
    110   for i:=1 to m do
    111     for j:=i to m do
    112     begin
    113       y:=g[j,m];
    114       for x:=0 to g[1,i] do
    115       begin
    116         while (y>0) and (min(x+y-1+g[i,j],fl[i,x]+fr[j,y-1])>=min(x+y+g[i,j],fl[i,x]+fr[j,y])) do dec(y);
    117         max(f[i,j],min(x+y+g[i,j],fl[i,x]+fr[j,y]));
    118       end;
    119     end;
    120 
    121   for i:=1 to n do
    122   begin
    123     ans:=0;
    124     for x:=1 to s[i] do
    125       for y:=e[i] to m do
    126         max(ans,f[x,y]);
    127     writeln(ans);
    128   end;
    129 end.
    View Code

     

  • 相关阅读:
    Linux异步IO
    基本数据类型总结--
    总结
    字典魔法二
    字典及其魔法
    元祖的魔法
    列表的特点
    运算符
    while ……else……和while……continue……和 while…………break…………
    作业---写一个程序,用户名 、密码输入错误3次 错误
  • 原文地址:https://www.cnblogs.com/phile/p/4610759.html
Copyright © 2020-2023  润新知