分组赛讲课讲了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 (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.
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.