• APIO2015题解


    分组赛讲课讲了APIO2015的题,于是回去就做完了

    稍微写一点题解吧

    bzoj4069 逐位处理的简单题,然后就是bool型dp

    然后a=1 的时候可以把一位状态干掉

    当一维状态单调且是bool型dp时,我们可以用dp表示这一维状态;类似的思想也在bzoj1937出现过

     1 var s:array[0..2010] of int64;
     2     n,a,b,i,j,k,p:longint;
     3     g,c:array[0..2010] of longint;
     4     f:array[0..110,0..110] of boolean;
     5     now:int64;
     6     can:boolean;
     7 
     8 function min(a,b:longint):longint;
     9   begin
    10     if a>b then exit(b) else exit(a);
    11   end;
    12 
    13 begin
    14   readln(n,a,b);
    15   for i:=1 to n do
    16   begin
    17     read(c[i]);
    18     s[i]:=s[i-1]+c[i];
    19   end;
    20   if a=1 then
    21   begin
    22     for p:=40 downto 0 do
    23     begin
    24       now:=now or int64(1) shl int64(p);
    25       g[0]:=0;
    26       for i:=1 to n do
    27         g[i]:=n+1;
    28       for i:=1 to n do
    29         for j:=1 to i do
    30         begin
    31           if (s[i]-s[j-1]) and now>0 then continue;  //当前模板是0就不能为1,是1就随意,这里转化一下方便快速匹配
    32           g[i]:=min(g[i],g[j-1]+1);
    33         end;
    34       if g[n]>b then
    35         now:=now xor int64(1) shl int64(p);
    36     end;
    37   end
    38   else begin
    39     for p:=40 downto 0 do
    40     begin
    41       now:=now or int64(1) shl int64(p);
    42       fillchar(f,sizeof(f),false);
    43       f[0,0]:=true;
    44       for i:=1 to n do
    45         for j:=1 to n do
    46           for k:=1 to i do
    47             if f[k-1,j-1] then
    48             begin
    49               f[i,j]:=((s[i]-s[k-1]) and now=0);
    50               if f[i,j] then break;
    51             end;
    52 
    53       can:=false;
    54       for i:=a to b do
    55         if f[n,i] then
    56         begin
    57           can:=true;
    58           break;
    59         end;
    60       if not can then now:=now xor int64(1) shl int64(p);
    61     end;
    62   end;
    63   for p:=40 downto 0 do
    64     now:=now xor int64(1) shl int64(p);
    65   writeln(now);
    66 end.
    4069

    bzoj4070 听说现场直接爆搜就过了,这……

    首先每只狗只会往一个方向跳

    当pi大的时候,每只狗跳的次数少,直接建图即可

    当pi小的时候,每个点向外走的种类很少,建立辅助点即可

    经典的分类思想,设定一个K

    当pi>k,直接建图,设n个点为(i,0)

    然后每个点i再建立k个辅助点(i,1)~(i,k) 代表对应跳跃能力

    然后看每条狗,如果pi<=k则连向对应的辅助点

    然后每个辅助点连向(i,0),表示通过(i,0)可以停下来换狗

    然后跑dijkstra即可

    注意k不能太大,因为内存卡得比较紧

    然后我又tle了,把pi离散化后就过了……

      1 const inf=10000007;
      2 type node=record
      3        po,next,num:longint;
      4      end;
      5      point=record
      6        loc,num:longint;
      7      end;
      8 
      9 var h:array[0..3100010] of point;
     10     e:array[0..15000010] of node;
     11     p,d,wh:array[0..3100010] of longint;
     12     v,c,b,f:array[0..30010] of longint;
     13     w:array[0..30010,0..110] of longint;
     14     r,st,en,size,i,j,tot,t,x,y,n,m,len:longint;
     15 
     16 procedure add(x,y,z:longint);
     17   begin
     18     inc(len);
     19     e[len].po:=y;
     20     e[len].next:=p[x];
     21     e[len].num:=z;
     22     p[x]:=len;
     23   end;
     24 
     25 procedure swap(var a,b:point);
     26   var c:point;
     27   begin
     28     c:=a;
     29     a:=b;
     30     b:=c;
     31   end;
     32 
     33 procedure sift(i:longint);
     34   var j,x,y:longint;
     35   begin
     36     j:=i shl 1;
     37     while j<=tot do
     38     begin
     39       if (j<tot) and (h[j].num>h[j+1].num) then inc(j);
     40       if h[i].num>h[j].num then
     41       begin
     42         x:=h[i].loc;
     43         y:=h[j].loc;
     44         wh[x]:=j;
     45         wh[y]:=i;
     46         swap(h[i],h[j]);
     47         i:=j;
     48         j:=i shl 1;
     49       end
     50       else break;
     51     end;
     52   end;
     53 
     54 procedure up(i:longint);
     55   var j,x,y:longint;
     56   begin
     57     j:=i shr 1;
     58     while j>0 do
     59     begin
     60       if h[i].num<h[j].num then
     61       begin
     62         x:=h[i].loc;
     63         y:=h[j].loc;
     64         wh[x]:=j;
     65         wh[y]:=i;
     66         swap(h[i],h[j]);
     67         i:=j;
     68         j:=i shr 1;
     69       end
     70       else break;
     71     end;
     72   end;
     73 
     74 begin
     75   readln(n,m);
     76   for i:=1 to m do
     77   begin
     78     readln(b[i],f[i]);
     79     inc(b[i]);
     80     if i=1 then st:=b[i];
     81     if i=2 then en:=b[i];
     82     v[f[i]]:=1;
     83   end;
     84   for i:=1 to n do
     85     if v[i]=1 then
     86     begin
     87       inc(r);
     88       c[r]:=i;
     89       v[i]:=r;
     90     end;
     91 
     92   size:=trunc(sqrt(r));
     93   if size>100 then size:=100;
     94   t:=n;
     95   for i:=1 to size do
     96   begin
     97     for j:=1 to n do
     98     begin
     99       inc(t);
    100       w[j,i]:=t;
    101       add(t,j,0);
    102     end;
    103     for j:=1 to n-c[i] do
    104     begin
    105       add(w[j,i],w[j+c[i],i],1);
    106       add(w[j+c[i],i],w[j,i],1);
    107     end;
    108   end;
    109 
    110   for i:=1 to m do
    111     if f[i]<=c[size] then
    112       add(b[i],w[b[i],v[f[i]]],0)
    113     else begin
    114       j:=1;
    115       while true do
    116       begin
    117         if b[i]+f[i]*j>n then break;
    118         add(b[i],b[i]+f[i]*j,j);
    119         inc(j);
    120       end;
    121       j:=1;
    122       while true do
    123       begin
    124         if b[i]-f[i]*j<=0 then break;
    125         add(b[i],b[i]-f[i]*j,j);
    126         inc(j);
    127       end;
    128     end;
    129 
    130   tot:=1;
    131   h[1].loc:=st;
    132   h[1].num:=0;
    133   for i:=1 to t do
    134     if i<>st then
    135     begin
    136       inc(tot);
    137       h[tot].loc:=i;
    138       h[tot].num:=inf;
    139       d[i]:=inf;
    140       wh[i]:=tot;
    141     end;
    142 
    143   while tot>0 do
    144   begin
    145     x:=h[1].loc;
    146     if x=en then break;
    147     if h[1].num=inf then break;
    148     wh[h[tot].loc]:=1;
    149     swap(h[1],h[tot]);
    150     dec(tot);
    151     sift(1);
    152     i:=p[x];
    153     while i<>0 do
    154     begin
    155       y:=e[i].po;
    156       if d[y]>d[x]+e[i].num then
    157       begin
    158         d[y]:=d[x]+e[i].num;
    159         h[wh[y]].num:=d[y];
    160         up(wh[y]);
    161       end;
    162       i:=e[i].next;
    163     end;
    164   end;
    165   if d[en]=inf then writeln(-1)
    166   else writeln(d[en]);
    167 end.
    4070

    bzoj4071 一开始看题的时候想到的是三分套三分……好像听说也能过……

    我们只需要考虑起点终点在两侧的

    当k=1 大家都会是中位数贪心

    当k=2 分类讨论,设第一座桥在S1,第二座桥在S2

    不难得到,xi+yi<S1+S2时走S1,否则走S2

    这样只要对x+y排序,枚举分割点,分别对两部分求中位数即可然后在求和即可

    这我们可以用权值线段树维护

    顺便在UOJ上交被叉掉了,没事卡什么快排真是了……

      1 type node=record
      2        x,y,s:longint;
      3      end;
      4      point=record
      5        s:longint;
      6        sum:int64;
      7      end;
      8 
      9 var c,a:array[0..200010] of longint;
     10     b:array[0..100010] of node;
     11     tree:array[0..200010*4,0..1] of point;
     12     x,y,n,t,mid,m,i,k:longint;
     13     ans,s:int64;
     14     ch1,ch2:char;
     15 
     16 procedure min(var a:int64; b:int64);
     17   begin
     18     if a>b then a:=b;
     19   end;
     20 
     21 procedure swap(var a,b:longint);
     22   var c:longint;
     23   begin
     24     c:=a;
     25     a:=b;
     26     b:=c;
     27   end;
     28 
     29 procedure sort(l,r:longint);
     30   var i,j,x:longint;
     31   begin
     32     i:=l;
     33     j:=r;
     34     x:=a[(l+r) shr 1];
     35     repeat
     36       while a[i]<x do inc(i);
     37       while x<a[j] do dec(j);
     38       if not(i>j) then
     39       begin
     40         swap(a[i],a[j]);
     41         inc(i);
     42         dec(j);
     43       end;
     44     until i>j;
     45     if l<j then sort(l,j);
     46     if i<r then sort(i,r);
     47   end;
     48 
     49 procedure qsort(l,r:longint);
     50   var i,j,x:longint;
     51       y:node;
     52   begin
     53     i:=l;
     54     j:=r;
     55     x:=b[(l+r) shr 1].s;
     56     repeat
     57       while b[i].s<x do inc(i);
     58       while x<b[j].s do dec(j);
     59       if not(i>j) then
     60       begin
     61         y:=b[i]; b[i]:=b[j]; b[j]:=y;
     62         inc(i);
     63         dec(j);
     64       end;
     65     until i>j;
     66     if l<j then qsort(l,j);
     67     if i<r then qsort(i,r);
     68   end;
     69 
     70 function find(l,r,x:longint):longint;
     71   var m:longint;
     72   begin
     73     while l<=r do
     74     begin
     75       m:=(l+r) shr 1;
     76       if c[m]=x then exit(m);
     77       if c[m]>x then r:=m-1 else l:=m+1;
     78     end;
     79   end;
     80 
     81 procedure add(i,l,r,w,x,y:longint);
     82   var m:longint;
     83   begin
     84     inc(tree[i,w].s,y);
     85     inc(tree[i,w].sum,y*c[x]);
     86     if l<>r then
     87     begin
     88       m:=(l+r) shr 1;
     89       if x<=m then add(i*2,l,m,w,x,y)
     90       else add(i*2+1,m+1,r,w,x,y);
     91     end;
     92   end;
     93 
     94 function get(i,l,r,w,k:longint):int64;
     95   var m:longint;
     96   begin
     97     if l=r then exit(int64(k)*int64(c[l]))
     98     else begin
     99       m:=(l+r) shr 1;
    100       if tree[i*2,w].s>=k then exit(get(i*2,l,m,w,k))
    101       else exit(tree[i*2,w].sum+get(i*2+1,m+1,r,w,k-tree[i*2,w].s));
    102     end;
    103   end;
    104 
    105 function sum(w,n:longint):int64;
    106   begin
    107     exit(tree[1,w].sum-2*get(1,1,m,w,n shr 1));
    108   end;
    109 
    110 begin
    111   readln(k,n);
    112   for i:=1 to n do
    113   begin
    114     read(ch1);
    115     read(x);
    116     read(ch2); read(ch2);
    117     readln(y);
    118     if ch1=ch2 then s:=s+abs(x-y)
    119     else begin
    120       inc(t);
    121       b[t].x:=x;
    122       b[t].y:=y;
    123       b[t].s:=x+y;
    124     end;
    125   end;
    126   n:=t;
    127   t:=0;
    128   for i:=1 to n do
    129   begin
    130     inc(t);
    131     a[t]:=b[i].x;
    132     inc(t);
    133     a[t]:=b[i].y;
    134   end;
    135   sort(1,t);
    136   if k=1 then
    137   begin
    138     x:=a[(t+1) shr 1];
    139     ans:=0;
    140     for i:=1 to t do
    141       ans:=ans+abs(x-a[i]);
    142   end
    143   else begin
    144     qsort(1,n);
    145     m:=1;
    146     c[1]:=a[1];
    147     for i:=2 to t do
    148       if a[i]<>a[i-1] then
    149       begin
    150         inc(m);
    151         c[m]:=a[i];
    152       end;
    153     mid:=a[t shr 1];
    154     for i:=1 to n do
    155       ans:=ans+abs(b[i].x-mid)+abs(b[i].y-mid);
    156     for i:=1 to n do
    157     begin
    158       b[i].x:=find(1,m,b[i].x);
    159       b[i].y:=find(1,m,b[i].y);
    160       add(1,1,m,1,b[i].x,1);
    161       add(1,1,m,1,b[i].y,1);
    162     end;
    163     for i:=1 to n do
    164     begin
    165       add(1,1,m,0,b[i].x,1);
    166       add(1,1,m,0,b[i].y,1);
    167       add(1,1,m,1,b[i].x,-1);
    168       add(1,1,m,1,b[i].y,-1);
    169       min(ans,sum(0,i*2)+sum(1,t-i*2));
    170     end;
    171   end;
    172   writeln(ans+s+n);
    173 end.
    4071
  • 相关阅读:
    Codeforces Round 49 C-Minimum Value Rectangle(最小面积周长比)
    牛客网暑假训练第五场——F take(树状数组求概率期望)
    牛客网暑假训练第九场——F-Typing practice(多串并行 优化KMP详解)
    POJ
    牛客网暑假训练第九场——E Music Game(概率期望)
    2018 ACM 国际大学生程序设计竞赛上海大都会赛——J Beautiful Numbers(数位DP)
    牛客网暑假训练第五场——A gpa(01分数规划)
    POJ
    UPC-6623 MUL(最大权闭合子图)
    HDU-6380 degree(图论&并查集)
  • 原文地址:https://www.cnblogs.com/phile/p/4573291.html
Copyright © 2020-2023  润新知