分组赛讲课讲了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.
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 (jand (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 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.
bzoj4071 一开始看题的时候想到的是三分套三分……好像听说也能过……
我们只需要考虑起点终点在两侧的
当k=1 大家都会是中位数贪心
当k=2 分类讨论,设第一座桥在S1,第二座桥在S2
不难得到,xi+yi 这样只要对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]