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
原文地址:https://www.cnblogs.com/phile/p/4573291.html