17.11.25B组总结
T1
考试是打了2500+的暴力,30。
其实正解思路需要很有经验的选手才能想到,即将所有操作构为一棵树,再在树上进行递归暴力,对于还有20分一条链,会栈溢出,直接循环即可。
80分:
var
a,b:array[0..1000000]of longint;
tov,next,last,d,ch,y,ans:array[0..1000000]of longint;
n,k,tot,i,z,t,bz:longint;
procedure insert(x,y:longint);
begin
inc(tot);
tov[tot]:=y;
next[tot]:=last[x];
last[x]:=tot;
end;
function find(l,r:longint):longint;
var
mid:longint;
begin
while l<r do
begin
mid:=(l+r) div 2;
if d[mid]>=z then
r:=mid
else
l:=mid+1;
end;
exit(r);
end;
procedure dfs(x:longint);
var
i,yy:longint;
begin
i:=last[x];
while i>0 do
begin
yy:=tov[i];
i:=next[i];
if a[yy]=0 then
begin
if b[yy]>d[t] then
begin
inc(t);
d[t]:=b[yy];
ch[yy]:=t;
y[yy]:=0;
end
else
begin
z:=b[yy];
k:=find(1,t);
y[yy]:=d[k];
ch[yy]:=k;
d[k]:=b[yy];
end;
end
else
ch[yy]:=0;
ans[yy]:=t;
dfs(yy);
end;
if ch[x]=0 then
exit;
d[ch[x]]:=y[x];
if (ch[x]=t)and(y[x]=0) then
dec(t);
end;
begin
readln(n);
d[0]:=-maxlongint;
t:=0;
for i:=1 to n do
begin
readln(a[i],b[i]);
if a[i]=0 then
insert(i-1,i)
else
insert(b[i],i);
end;
dfs(0);
for i:=1 to n do
writeln(ans[i]);
end.
另外20:
var
a,b:array[0..1000000]of longint;
tov,next,last,d,ch,y,ans:array[0..1000000]of longint;
n,k,tot,i,z,t,bz:longint;
procedure insert(x,y:longint);
begin
inc(tot);
tov[tot]:=y;
next[tot]:=last[x];
last[x]:=tot;
end;
function find(l,r:longint):longint;
var
mid:longint;
begin
while l<r do
begin
mid:=(l+r) div 2;
if d[mid]>=z then
r:=mid
else
l:=mid+1;
end;
exit(r);
end;
begin
readln(n);
d[0]:=-maxlongint;
t:=0;
for i:=1 to n do
readln(a[i],b[i]);
for i:=1 to n do
begin
if a[i]=0 then
begin
if b[i]>d[t] then
begin
inc(t);
d[t]:=b[i];
ch[i]:=t;
y[i]:=0;
end
else
begin
z:=b[i];
k:=find(1,t);
y[i]:=d[k];
ch[i]:=k;
d[k]:=b[i];
end;
end
else
ch[i]:=0;
writeln(t);
end;
end.
T2
考试时理解错题意,爆0。
正解有四个数组,递推。每次将
(i+1)3,(i+1)2
与
(i+1)
维护,再每次更新DP数组
f[i]:=f[i−1]+f3[i]−f3[i−1]∗x
。
var
n,i,j:longint;
f,f1,f2,f3:array[0..100000]of extended;
x:extended;
begin
readln(n);
for i:=1 to n do
begin
readln(x);
f1[i]:=(f1[i-1]+1)*x;
f2[i]:=(f2[i-1]+f1[i-1]*2+1)*x;
f3[i]:=(f3[i-1]+f2[i-1]*3+f1[i-1]*3+1)*x;
f[i]:=f[i-1]+f3[i]-x*f3[i-1];
end;
writeln(f[n]:0:1);
end.
T3
最简单的一题,先用SPFA维护出k个点互相之间的距离,再DFS即可。
注意初值稍微大一点,判断-1。
var
que,next,last,len,tov,dis:array[0..100000]of longint;
exist:array[0..100000]of boolean;
dist:array[0..15,0..15]of int64;
g,bz:array[0..15]of longint;
head,tail,n,m,i,x,y,z,tot,k,s,t:longint;
ans:int64;
procedure insert(x,y,z:longint);
begin
inc(tot);
tov[tot]:=y;
len[tot]:=z;
next[tot]:=last[x];
last[x]:=tot;
end;
procedure spfa(cc,c:longint);
var
x,y,i:longint;
begin
fillchar(que,sizeof(que),0);
fillchar(exist,sizeof(exist),0);
fillchar(dis,sizeof(dis),0);
que[1]:=c;
exist[c]:=true;
head:=0;
tail:=1;
for i:=1 to n do
dis[i]:=maxlongint div 2;
dis[c]:=0;
while head<>tail do
begin
head:=head mod n+1;
x:=que[head];
i:=last[x];
while i<>0 do
begin
y:=tov[i];
if dis[y]>dis[x]+len[i] then
begin
dis[y]:=dis[x]+len[i];
if not exist[y] then
begin
tail:=tail mod n+1;
que[tail]:=y;
exist[y]:=true;
end;
end;
i:=next[i];
end;
exist[x]:=false;
end;
for i:=0 to k+1 do
dist[cc,i]:=dis[g[i]];
end;
procedure dg(x,ge:longint;sum:int64);
var
i:longint;
begin
if sum>=ans then
exit;
if ge=k+1 then
begin
inc(sum,dist[x,k+1]);
if sum>=ans then
exit;
ans:=sum;
exit;
end;
for i:=0 to k do
if (bz[i]=0)and(sum+dist[x,i]<ans) then
begin
bz[i]:=1;
dg(i,ge+1,sum+dist[x,i]);
bz[i]:=0;
end;
end;
begin
readln(n,m,k,s,t);
for i:=1 to m do
begin
readln(x,y,z);
insert(x,y,z);
end;
g[0]:=s;
g[k+1]:=t;
for i:=1 to k do
readln(g[i]);
fillchar(dist,sizeof(dist),63);
for i:=0 to k+1 do
spfa(i,g[i]);
bz[0]:=1;
ans:=maxlongint*2;
dg(0,1,0);
if ans=1073741823 then
writeln(-1)
else
writeln(ans);
end.