17.10.7B组总结
今天的比赛如下所示:
淼∗淼=淼2
可惜我没AK,(⊙o⊙)…
T1
我自豪地表示我打了正解。
由于这题可以用二分,所以我一言不合用了二分,DP判断时发现仍有时超可能,且答案具有线性,于是我又用了单调队列。
判断过程:
function pd(x:longint):boolean;
var
i,st,en,j:longint;
g,d:array[0..50000]of longint;
begin
fillchar(g,sizeof(g),0);
fillchar(d,sizeof(d),0);
st:=1;
en:=1;
for i:=1 to n+1 do
begin
while (st<=en)and(d[st]<i-x-1) do
inc(st);
g[i]:=g[d[st]]+a[i];
while (st<=en)and(g[d[en]]>g[i]) do
dec(en);
inc(en);
d[en]:=i;
end;
if g[n+1]>t then
exit(false);
exit(true);
end;
T2
第一眼看到这题,我便想到了曾经做过的——锻炼身体(https://jzoj.net/senior/#main/show/1753)
于是有了与此题类似的DP想法,设f[i,j,k]表示到了第i个时间段,j行k列的最大移动步数。方程显然。
听说正解用了单调队列,今天是单调队列专题?
uses math;
var
n,m,x,y,k,i,j,l,ans,xx,yy,tot:longint;
a:array[0..200,0..200]of longint;
c:array[0..200,1..3]of longint;
f:array[0..201,0..200,0..200]of longint;
fx:array[0..4,1..2]of longint=((0,0),(-1,0),(1,0),(0,-1),(0,1));
ch:char;
begin
readln(n,m,x,y,k);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(ch);
if ch='.' then
a[i,j]:=1;
end;
readln;
end;
f[1,x,y]:=1;
for i:=1 to k do
begin
readln(c[i,1],c[i,2],c[i,3]);
for j:=1 to n do
for l:=1 to m do
if f[i,j,l]<>0 then
begin
f[i+1,j,l]:=max(f[i+1,j,l],f[i,j,l]);
xx:=j;
yy:=l;
tot:=0;
while true do
begin
inc(xx,fx[c[i,3],1]);
inc(yy,fx[c[i,3],2]);
inc(tot);
if (xx>0)and(yy>0)and(xx<=n)and(yy<=m)and(a[xx,yy]=1)and(tot-1<=c[i,2]-c[i,1]) then
f[i+1,xx,yy]:=max(f[i+1,xx,yy],f[i,j,l]+tot)
else
break;
ans:=max(ans,f[i+1,xx,yy]);
end;
end;
end;
writeln(ans-1);
end.
T3
比赛唯一没对的题,其实挺简单的,想到思路一码就过。
容易想到,对于两个点,最长边的最小值定在这个图的最小生成树上,于是我们可以删掉无用的边。接着再将这两个点到他们的LCA(最近公共祖先)找出来,答案就在这条路径上。
uses math;
var
i,n,m,k,gx,gy,op,x,y,tot,j,r:longint;
a:array[0..30000,1..3] of longint;
fa,d:array[0..15000] of longint;
tov,next,last,len:array[0..80000] of longint;
f:array[0..80000,1..2] of longint;
g,wer:array[0..15000,0..16] of longint;
procedure kp(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(l+r) div 2,3];
repeat
while a[i,3]<mid do inc(i);
while a[j,3]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then kp(l,j);
if i<r then kp(i,r);
end;
function get(k:longint):longint;
begin
if fa[k]=0 then
exit(k);
fa[k]:=get(fa[k]);
exit(fa[k]);
end;
procedure insert(x,y,z:longint);
begin
inc(tot);
tov[tot]:=y;
len[tot]:=z;
next[tot]:=last[x];
last[x]:=tot;
end;
procedure dg(t,y:longint);
var
i:longint;
begin
d[t]:=d[y]+1;
i:=last[t];
while i<>0 do
begin
if tov[i]<>y then
begin
dg(tov[i],t);
f[tov[i],1]:=t;
f[tov[i],2]:=len[i];
end;
i:=next[i];
end;
end;
function lca(x,y:longint):longint;
var
k:longint;
begin
lca:=-maxlongint;
while d[x]<d[y] do
begin
lca:=max(lca,f[y,2]);
y:=f[y,1];
end;
while d[x]>d[y] do
begin
lca:=max(lca,f[x,2]);
x:=f[x,1];
end;
while x<>y do
begin
lca:=max(lca,f[y,2]);
y:=f[y,1];
lca:=max(lca,f[x,2]);
x:=f[x,1];
end;
end;
begin
readln(n,m,k);
for i:=1 to m do
readln(a[i,1],a[i,2],a[i,3]);
kp(1,m);
for i:=1 to m do
if get(a[i,1])<>get(a[i,2]) then
begin
insert(a[i,1],a[i,2],a[i,3]);
insert(a[i,2],a[i,1],a[i,3]);
gx:=get(a[i,1]);
gy:=get(a[i,2]);
fa[gx]:=gy;
end;
dg(1,0);
for i:=1 to k do
begin
readln(x,y);
writeln(lca(x,y));
end;
end.