您的位置:首页 > 其它

【NOIP提高组五校联考】排队

2016-10-05 21:25 316 查看

Description



Solution

因为每一个房间的优先级是固定的,所以可以预处理出每个房间的优先级,以此作为凭证把它插入堆中,很显然较优先的房间若是空的就一定会选取到,那么一次插入若干个人,就进行同样次数的取顶操作。记录那些点已经被占用了,显然被占用的房间一定是连续的,只要找到开头,第二问就能轻松解决,倍增就可以快速解决了。(比赛的时候想太多了,以为可能经过操作后被占用房间会断开,所以没有打倍增……)

Code

var
next,data:array[0..200000] of longint;
last,l1,l2,t,dfn,de,p:array[0..100000] of longint;
f:array[0..100000,0..20] of longint;
n,m,op,q,x,y,i,j,sum,num:longint;
procedure ins(x,y:longint);
begin
inc(sum);
data[sum]:=y;
next[sum]:=last[x];
last[x]:=sum;
end;
procedure up(x:longint);
begin
if x div 2=0 then exit;
if dfn[t[x]]<dfn[t[x div 2]] then
begin
t[0]:=t[x];t[x]:=t[x div 2];t[x div 2]:=t[0];
up(x div 2);
exit;
end;
end;
procedure down(x:longint);
var s:longint;
begin
s:=x;
if (x*2<=sum)and(dfn[t[s]]>dfn[t[x*2]]) then s:=x*2;
if (x*2+1<=sum)and(dfn[t[s]]>dfn[t[x*2+1]]) then s:=x*2+1;
if s=x then exit;
t[0]:=t[x];t[x]:=t[s];t[s]:=t[0];
down(s);
end;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
i:=l;j:=r;
mid:=t[(i+j)div 2];
repeat
while t[i]>mid do inc(i);
while mid>t[j] do dec(j);
if i<=j then
begin
t[0]:=t[i];t[i]:=t[j];t[j]:=t[0];
inc(i); dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure dfs(x,fa:longint);
var i:longint;
begin
i:=last[x];num:=0;
while i<>0 do
begin
if data[i]<>fa then
begin
inc(num);
t[num]:=data[i];
end;
i:=next[i];
end;
qsort(1,num);
for i:=1 to num do
begin
inc(sum);
l1[sum]:=x;l2[sum]:=t[i];
end;
i:=last[x];
while i<>0 do
begin
if data[i]<>fa then dfs(data[i],x);
i:=next[i];
end;
end;
procedure deal(x,fa,deep:longint);
var i:longint;
begin
de[x]:=deep;
f[x,0]:=fa; i:=1;
while f[f[x,i-1],i-1]<>0 do
begin
f[x,i]:=f[f[x,i-1],i-1];
inc(i);
end;
i:=last[x];
while i<>0 do
begin
deal(data[i],x,deep+1);
i:=next[i];
end;
inc(num);dfn[x]:=num;
inc(sum);t[sum]:=x;
up(sum);
end;
function jump(x:longint):longint;
var i:longint;
begin
jump:=x;
while p[f[jump,0]]=1 do
begin
i:=1;
while p[f[jump,i]]=1 do inc(i);
dec(i);
jump:=f[jump,i];
end;
exit(jump);
end;
begin
readln(n,m);
for i:=1 to n-1 do
begin
readln(x,y);
ins(x,y); ins(y,x);
end;
sum:=0;
dfs(1,0);
fillchar(data,sizeof(data),0);
fillchar(last,sizeof(last),0);
fillchar(next,sizeof(next),0);
fillchar(t,sizeof(t),0);
sum:=0;
for i:=1 to n-1 do ins(l1[i],l2[i]);
sum:=0;num:=0;
deal(1,0,1);
for i:=1 to m do
begin
readln(op,q);
case op of
1:
for j:=1 to q do
begin
if j=q then writeln(t[1]);
p[t[1]]:=1;t[1]:=0;
t[0]:=t[sum];t[sum]:=t[1];t[1]:=t[0];
dec(sum); down(1);
end;
2:
begin
x:=jump(q);
writeln(de[q]-de[x]);
p[x]:=0;
inc(sum);
t[sum]:=x;
up(sum);
end;
end;
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NOIP 五校联考 倍增