求noip2012提高组复赛题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求noip2012提高组复赛题解相关的知识,希望对你有一定的参考价值。

RT

参考技术A 第一题:
program dig;
type
typearr=record
y,t:longint; s:double;
end;
var
a:array[1..20000] of typearr;
t:array[1..10000] of longint;
q:array[1..10000] of longint;
v:array[1..10000] of boolean;
f:array[1..10000] of double;
x:array[1..10000] of double;
y:array[1..10000] of double;
i,j,k,n,l,r,v1,v2,xx,yy,zz,sum,head,tail,total:longint;
s,ss,tt:double;
procedure add(x,y:longint;s:double);
begin
inc(total);
a[total].y:=y;
a[total].s:=s;
a[total].t:=t[x];
t[x]:=total;
end;
function getlen(a,b:longint):double;
begin
exit(sqrt(sqr(x[a]-x[b])+sqr(y[a]-y[b])));
end;
procedure worknode(a,b,c:longint);
var
k,l,xx,yy,ss:double;
begin
k:=(x[a]-x[b])/(y[a]-y[b]);
l:=x[a]-y[a]*k;
yy:=y[c];
xx:=y[c]*k+l;
sum:=sum+1;
x[sum]:=xx;
y[sum]:=yy;
ss:=x[c]-xx;
add(sum,c,ss/v2);
add(c,sum,ss/v2);
end;
begin
assign(input,'dig.in'); reset(input);
assign(output,'dig.out'); rewrite(output);
readln(n); sum:=n;
readln(v1,v2);
for i:=1 to n do readln(x[i],y[i]);
for i:=1 to n-1 do
begin
s:=getlen(i,i+1);
add(i,i+1,s/v1);
add(i+1,i,s/v1);
end;
for i:=1 to n do
begin
l:=i-1; r:=i+1;
while l>1 do
begin
if (y[i]-y[l])*(y[i]-y[l-1])<0 then
begin
worknode(l-1,l,i);
break;
end;
if y[i]=y[l] then
begin
s:=x[i]-x[l];
add(i,l,s/v2);
add(l,i,s/v2);
break;
end;
if y[i]=y[l-1] then
begin
s:=x[i]-x[l-1];
add(i,l-1,s/v2);
add(l-1,i,s/v2);
break;
end;
dec(l);
end;
while r<n-1 do
begin
if (y[i]-y[r])*(y[i]-y[r+1])<0 then
begin
worknode(r+1,r,i);
break;
end;
if y[i]=y[r] then
begin
s:=x[r]-x[i];
add(i,r,s/v2);
add(r,i,s/v2);
break;
end;
if y[i]=y[r+1] then
begin
s:=x[r+1]-x[i];
add(i,r+1,s/v2);
add(r,i+1,s/v2);
break;
end;
inc(r);
end;
end;
for i:=1 to 10000 do f[i]:=1e20;
q[1]:=1; f[1]:=0; v[1]:=true; tail:=1;
while head<>tail do
begin
head:=head mod 10000+1;
zz:=q[head];
v[zz]:=false;
xx:=t[zz];
while xx<>0 do
begin
yy:=a[xx].y;
ss:=a[xx].s;
if f[zz]+ss<f[yy] then
begin
f[yy]:=f[zz]+ss;
if not v[yy] then
begin
tail:=tail mod 10000+1;
q[tail]:=yy;
v[yy]:=true;
end;
end;
xx:=a[xx].t;
end;
end;
writeln(f[n]:0:6);
close(input); close(output);
end.

第二题
program flycar;
var
a:array[1..5000,1..3] of longint;
f:array[1..1000] of longint;
i,j,k,n,m,x,y,z,p,max,min,start,goal:longint;
function find(v:longint):longint;
begin
if f[v]=v then exit(v);
f[v]:=find(f[v]);
exit(f[v]);
end;
procedure swap(var a,b:longint);
var
t:longint;
begin
t:=a; a:=b; b:=t;
end;
procedure sort(i,j:longint);
var
l,r,x:longint;
begin
l:=i; r:=j; x:=a[(l+r)>>1,3];
repeat
while a[l,3]<x do inc(l);
while a[r,3]>x do dec(r);
if l<=r then
begin
swap(a[l,1],a[r,1]);
swap(a[l,2],a[r,2]);
swap(a[l,3],a[r,3]);
inc(l);
dec(r);
end;
until l>r;
if r>i then sort(i,r);
if l<j then sort(l,j);
end;
function check(x,ll:longint):boolean;
var
i,j,k,l,r,yy,xx,rr,fa1,fa2,mid:longint;
begin
l:=ll; r:=m; rr:=ll;
while l<=r do
begin
mid:=(l+r)>>1;
if a[mid,3]-a[ll,3]<=x
then begin rr:=mid; l:=mid+1; end
else r:=mid-1;
end;
for i:=1 to n do f[i]:=i;
for i:=ll to rr do
begin
xx:=a[i,1];
yy:=a[i,2];
fa1:=find(xx);
fa2:=find(yy);
if fa1<>fa2 then f[fa1]:=fa2;
end;
if find(start)=find(goal)
then exit(true)
else exit(false);
end;
procedure work;
var
i,l,r,mid,best:longint;
flag:boolean;
begin
readln(start,goal);
l:=0;
r:=max-min;
while l<=r do
begin
mid:=(l+r)>>1;
flag:=false;
for i:=1 to m-1 do
if check(mid,i) then
begin
flag:=true; break;
end;
if flag then begin best:=mid; r:=mid-1; end
else l:=mid+1;
end;
writeln(best);
end;
begin
assign(input,'flycar.in'); reset(input);
assign(output,'flycar.out'); rewrite(output);
readln(n,m);
min:=maxlongint;
for i:=1 to m do
begin
readln(x,y,z);
if z<min then min:=z;
if z>max then max:=z;
a[i,1]:=x;
a[i,2]:=y;
a[i,3]:=z;
end;
sort(1,m);
readln(p);
for i:=1 to p do work;
close(input); close(output);
end.

第三题
program poj_2553;
var
s:array[1..5000,1..5000] of longint;
a:array[1..1000000,1..2] of longint;
belong:array[1..5000] of longint;
stack:array[1..5000] of longint;
num:array[1..5000] of longint;
dfn:array[1..5000] of longint;
low:array[1..5000] of longint;
map:array[1..5000] of longint;
ans:array[1..5000] of longint;
vv:array[1..5000] of boolean;
i,j,k,n,m,x,y,r,time,top,sum,total:longint;
flag:boolean;
procedure init;
begin
top:=0; total:=0; time:=0; sum:=0; r:=0;
fillchar(vv,sizeof(vv),0);
fillchar(low,sizeof(low),0);
fillchar(dfn,sizeof(dfn),0);
fillchar(num,sizeof(num),0);
fillchar(map,sizeof(map),0);
fillchar(belong,sizeof(belong),0);
end;
procedure add(x,y:longint);
begin
inc(total);
a[total,1]:=y;
a[total,2]:=map[x];
map[x]:=total;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a); exit(b);
end;
procedure tarjan(v:longint);
var
i,j,k,x,y,z:longint;
begin
inc(time);
dfn[v]:=time;
low[v]:=time;
vv[v]:=true;
inc(top);
stack[top]:=v;
x:=map[v];
while x<>0 do
begin
y:=a[x,1];
if dfn[y]=0 then
begin
tarjan(y);
low[v]:=min(low[v],low[y]);
end
else
if vv[y] then
low[v]:=min(low[v],dfn[y]);
x:=a[x,2];
end;
if dfn[v]=low[v] then
begin
inc(sum);
repeat
x:=stack[top]; dec(top);
vv[x]:=false;
inc(num[sum]);
belong[x]:=sum;
s[sum,num[sum]]:=x;
until x=v;
end;
end;
procedure work(p:longint);
var
i,j,x,y,z:longint;
begin
for i:=1 to num[p] do
begin
z:=s[p,i];
x:=map[z];
while x<>0 do
begin
y:=a[x,1];
if belong[y]<>p then
begin
flag:=false; exit;
end;
x:=a[x,2];
end;
end;
end;
procedure swap(var a,b:longint);
var
t:longint;
begin
t:=a; a:=b; b:=t;
end;
procedure sort(i,j:longint);
var
l,r,x:longint;
begin
l:=i; r:=j; x:=ans[(l+r)>>1];
repeat
while ans[l]<x do inc(l);
while ans[r]>x do dec(r);
if l<=r then
begin
swap(ans[l],ans[r]);
inc(l);
dec(r);
end;
until l>r;
if r>i then sort(i,r);
if l<j then sort(l,j);
end;
begin
read(n);
while n<>0 do
begin
readln(m); init;
for i:=1 to m do
begin
read(x,y); add(x,y);
end;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
for i:=1 to sum do
begin
flag:=true;
work(i);
if flag then
for j:=1 to num[i] do
begin
inc(r);
ans[r]:=s[i,j];
end;
end;
sort(1,r);
if r<>0 then
begin
for i:=1 to r-1 do write(ans[i],' '); writeln(ans[r]);
end
else writeln;
read(n);
end;
end.
参考技术B 我只能说同求。。 。有了题也未必会。。。

同意的点个顶。。
参考技术C Day1:
第一题:后缀数组模板题,送分题。

第二题:可以证明最优解必然是连续的一个区间,枚举两个断点,其余点拆点做费用流即可。
第三题:考虑每个素数的指数,当没有乘以它的倍数的时候,比如p和2p这段范围内,是一个线性递推,矩阵快速幂秒掉。所以就枚举每个素数,分段n/p段做快速幂。不过注意高精度运算要用FFT来优化,有些根可以预处理出来的要先处理,不然还是要TLE。

Day2:
第一题:裸斜率优化,送分题。

第二题:比较烦的半平面交,需要模型转化。
第三题:此题比较麻烦,估计没有完美算法,标程是用线性规划来做的吧。其实可以根据数据范围,当m比较小的时候状压DP。大的时候可以用各种随机算法。
参考技术D 你以为我会泄题吗?哈哈哈哈,那你就错了 第5个回答  2012-11-07 Orz

以上是关于求noip2012提高组复赛题解的主要内容,如果未能解决你的问题,请参考以下文章

noip提高组的C语言历届复赛试题

noip需要准备哪些方面的基础知识。复赛需要做哪些类型的题目(提高组)?

noip需要准备哪些方面的基础知识.复赛需要做哪些类型的题目(提高组)?

noip2010普及组复赛接水问题

noip关于复赛要求的问题

2017.2.18[codevs1170]NOIP2008提高组复赛T4双栈排序