尼伯龙根之歌

 

 

【故事背景】

  北欧「末世神话」中,火神Loki挑唆黑暗之神Hoder杀死了光明之神Baldur,从而引导了「诸神之黄昏」不可避免的降临。而勇士Tristan作为亚瑟王麾下忠诚的Knight of Rounds之一,与其他Knight of Rounds一同受到了奥丁神的召唤。于是Tristan开始了他捍卫人类世界Midgard的任务。

题目一览

标题

危机!阿斯嘉特

精灵魔法

黎明与三色虹桥

世界树的试炼

源文件

asgard.pas/c/cpp

alfheim.pas/c/cpp

bifrost.pas/c/cpp

yggrasil.pas/c/cpp

输入文件

asgard.in

alfheim.in

bifrost.in

yggrasil.in

输出文件

asgard.out

alfheim.out

bifrost.out

yggrasil.out

测试点数目

20

10

10

10

总分值

100

100

100

100

时间限制

1s

1s

1s

2s

内存限制

128MB

128MB

128MB

128MB

Pro.1 危机!阿斯嘉特

【题目背景】

『火焰焚烧下的大地不断颤抖

  风中提线木偶摇摆着唱起颂歌

  辉耀般的星辰笼罩凄凉

  一望无际的鲜血开始沸腾!』

 

————《瓦尔基里福音书·第一乐章:绝望》————

【题目描述】

奥丁告诉Tristan,天界阿斯嘉特现在遭到了冥界邪恶亡灵的入侵。为了防止亡灵间谍混入英灵殿Valhalla,奥丁在英灵殿门口部署了T个女武神看守,每个女武神都有自己的特殊口令,只有(一个人或几个人共同)答出所有女武神的口令,才能进出英灵殿。而被允许进出英灵殿的勇敢战士亡灵共有M个,他们每个人都知道与其中K个女武神的口令。但为了稳妥,奥丁规定,只有当同时回答口令的战士数>=N时,他们才可能且一定能通过女武神的监察。现在奥丁已经规定好了M和N,他想知道,他至少需要多少个女武神。并且在女武神数量最少的情况下,每个战士亡灵最少需要知道多少个口令。

 

【输入格式】

一行两个数M,N。

 

【输出格式】

两行,每行一个正整数。第一行代表最少需要的女武神数量,第二行为在此情况下每个战士需要知道的最少口令数。

 

【样例输入】

3 2

 

【样例输出】

3

2

 

【时间限制】

1s

 

【数据范围】

对于20%的数据,1<= N<=M<=10;

对于100%的数据,1<=N<=M<=40。

 

【题目来源】

《末世神话:阿斯嘉特保卫战》

 //排列组合,数学问题

 

 

 

Pro.2 精灵魔法

【题目背景】

『谜题在丛林中散发芳香

绿叶上露珠跳跃着歌唱

火焰在隐暗的角落升腾飞起

月华照射着神祇们忠诚的信徒。』

 

————《瓦尔基里福音书·第六乐章:幻想》————

【题目描述】

Tristan解决了英灵殿的守卫安排后,便到达了静谧的精灵领地——Alfheim。由于Midgard处在Alfheim和冥界Hel的中间,精灵族领地尚未受到冥界恶灵的侵入。族长Galanodel为了帮助米德加尔特抵御外敌,对邪恶亡灵军团使用了高等魔法,从而使得亡灵军团每个士兵的行进速度变得不一致,从而打乱冥王Hel安排的最佳阵型。由于这个军团离Midgard还很远,因此在抵达Midgard之前,对于A、B两个亡灵,若A的初始位置在B后面且A的速度比B快,A就会冲到B的前面去。现在Galanodel想知道,会有多少对亡灵之间出现反超现象?

 

【输入格式】

第一行一个整数n,表示排成一队的邪恶亡灵军团有多少人。

第二行n个整数a[i],表示邪恶亡灵们在数轴上的初始坐标。数据保证这些坐标全部不同。亡灵军团向数轴正方向前进。

第三行n个整数v[i],表示邪恶亡灵们的行进速度。

 

【输出格式】

一行一个正整数k,表示「反超」的个数。

 

【样例输入】

3

1 2 3

2 1 3

 

【样例输出】

1

 

【时间限制】

1s

 

【数据范围】

对于30%的数据,1<= N<= 1000;

对于100%的数据,1<=N<= 10^5。

所有数据的绝对值均不超过maxlongint。

 

【题目来源】

《末世神话:精灵族的急援》

Pro.3 黎明与三色虹桥

【题目背景】

『恶魔收敛了漆黑邪恶的羽翼

  在天使面前温柔地保持安静

  牧师拥抱祭坛断续祈祷

  不停询问与阿斯嘉特还有多少距离。』

 

我认为也只有这道题最水 了,求逆序对

 

pascal code
program P2;
var n,i,j:longint;
ans:int64;
a,b:
array[0..100010]of longint;
p:
array[0..100010]of longint;
procedure qsort(l,r:longint);
var i,j,x,y,t:longint;
begin
i:
=l;j:=r;x:=a[(l+r) shr 1];y:=b[(l+r) shr 1];
repeat
while (a[i]<x)or((a[i]=x)and(b[i]<y)) do inc(i);
while (a[j]>x)or((a[j]=x)and(b[j]>y)) do dec(j);
if i<=j then
begin
t:
=a[i];a[i]:=a[j];a[j]:=t;
t:
=b[i];b[i]:=b[j];b[j]:=t;
inc(i);dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure msort(l,r:longint);
var i,j,m,k:longint;
begin
if l>=r then exit;
m:
=(l+r) shr 1;
msort(l,m);
msort(m
+1,r);
i:
=l;j:=m+1;k:=l;
repeat
if b[i]>b[j] then
begin
inc(ans,m
-i+1);
p[k]:
=b[j];
inc(j);inc(k);
end else
begin
p[k]:
=b[i];
inc(i);inc(k);
end;
until (i>m)or(j>r);
while (i<=m) do begin p[k]:=b[i];inc(i);inc(k);end;
while (j<=r) do begin p[k]:=b[j];inc(j);inc(k);end;
for i:=l to r do b[i]:=p[i];
end;
begin
readln(n);
for i:=1 to n do read(a[i]);
readln;
for i:=1 to n do read(b[i]);
readln;
qsort(
1,n);
msort(
1,n);
writeln(ans);
end.

 

 

 

 

————《瓦尔基里福音书·第三乐章:信仰》————

【题目描述】

Bifrost是连结神国Asgard和人类世界Midgard的桥梁,由三色——冰、火和空气——构成。Odin和Aser神族为了考验勇士Tristan,在Asgard的N个浮空岛屿之间建了M座虚无的三色虹桥Biforst。每座Bifrost的两端都各有一柄有两种状态【出鞘】和【封印】的魔法剑。Odin给Tristan留下的难题是:要给所有的魔法剑定下一个状态,使每个岛上处于两种不同状态的魔法剑数量相等,且每座桥两边的魔法剑必须处于不同状态。奥丁神还规定,第一座输入的Bifrost连结的编号较小浮空岛那端的剑已设置为【出鞘】状态且不可更改。

 

【输入格式】

输入第一行一个整数N。表示浮空岛个数N。第2行开始每行3个整数,表示每座Bifrost的编号和两端连结的浮空岛编号。输入0 0 0表示结束。

 

【输出格式】

按序换行输出每座Bifrost两端魔法剑的状态。Attack表示【出鞘】,Hiding表示【封印】。要求字典序最小,字典序最小指的是输出中所有Attack、Hiding连起来字典序最小。如样例输出的字典序是AttackHidingAttackHiding。无解输出“Your hero has fallen!”(不包括引号)。

 

【样例输入】

2

1 1 2

2 2 1

0 0 0

//欧拉回路,不很会 

 

 

【样例输出】

Attack Hiding

Attack Hiding

 

【时间限制】

1s

 

【数据范围】

对于100%的数据,1<=N<=200,数据保证所有浮空岛连通,不过两座浮空岛之间不一定只有一座Bifrost。

 

【题目来源】

《末世神话:希望之桥》

Pro.4 世界树的试炼

【题目背景】

『天空中的罪恶开始消弭

  云和霞光重新枝繁叶茂

  六弦琴在诗人手中低声吟唱

  歌颂芙蕾雅的恩惠终章。』

 

————《瓦尔基里福音书·第十乐章:重生》————

【题目描述】

勇士Tristan终于来到了世界树Yggrasil的脚下。作为世界的支柱,Yggrasil上的神祇们为Tristan设下了考验。Yggrasil将Tristan瞬间传送到了顶端,并把自己虚无化为N根横置于直角坐标系上的树枝。树枝有两个参数:左端点坐标和右端点坐标。所有树枝平行于X轴。Tristan一开始位于最上面的一根树枝的左端点。落到到每根树枝上后,他可以选择向左或向右走,但在同一根树枝上不得改变方向。Tristan的跑步速度和下落速度均为1单位长度/s。同时Tristan不能下落超过MaxHigh,否则他会摔死。Tristan已经看到他的伙伴们——Authur和Lancelot他们在树干上等他了,他必须尽快。你能帮他算出最短的落到X轴上的时间吗?

 

【输入格式】

输入第一行一个整数N。表示树枝根数。第二行到第N+1行每行三个整数x1,x2,y,表示这根树枝的左端横坐标,右端横坐标和高度(纵坐标)。第N+2行一个整数MaxHigh表示Tristan的最大下落高度。

 

【输出格式】

一行一个整数ans,表示Tristan落到X轴所需最短时间。若不管怎么样Tristan都会摔死,输出TP。

【样例输入】

2

1 3 2

1 1 1

2

 

【样例输出】

2

 

【时间限制】

2s

 

【数据范围】

对于100%的数据,1<=N<=100000。所有输入数据绝对值不超过maxlongint,所有树枝均位于X轴上方,树枝之间不会有点重叠或线重叠。

 

【题目来源】

《末世神话:忠诚之律》

这道题目官方给的标程是线段树+DP ,我刚开始做的时候就是只使用那种DP方法,但是严重超时。
见我们的磊哥用BFS AC 惊异,改成BFS 仍然纠结了我很长的时间,原因就是在更新状态的时候多了一点东西...

 

pascal code
program P4;
type node=record
a,b,x:longint;
end;
rec
=record
a,b,x,l,r,n:longint;
end;
var e:array[1..1000000]of node;
f:
array[1..1000000]of rec;
n,mh,i,j,k,head,tail,l,ans,max,min:longint;
flag:boolean;
procedure qsort(l,r:longint);
var i,j,x,y,z:longint;
begin
i:
=l;j:=r;x:=e[(l+r) shr 1].x;z:=e[(l+r) shr 1].a;
repeat
while (e[i].x>x)or((e[i].x=x)and(e[i].a<z)) do inc(i);
while (e[j].x<x)or((e[j].x=x)and(e[j].a>z)) do dec(j);
if i<=j then
begin
y:
=e[i].x;e[i].x:=e[j].x;e[j].x:=y;
y:
=e[i].a;e[i].a:=e[j].a;e[j].a:=y;
y:
=e[i].b;e[i].b:=e[j].b;e[j].b:=y;
inc(i);dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure swap(var a,b:longint);
var c:longint;
begin
c:
=a;a:=b;b:=c;
end;
begin
readln(n);
min:
=maxlongint;
max:
=-maxlongint;
for i:=1 to n do
with e[i] do
begin
readln(a,b,x);
if a>b then swap(a,b);
if a<min then min:=a;
if b>max then max:=b;
end;
readln(mh);
inc(n);
e[n].x:
=0;
e[n].a:
=min;
e[n].b:
=max;
qsort(
1,n);
ans:
=maxlongint;
head:
=0;tail:=1;
f[
1].a:=e[1].a;
f[
1].b:=e[1].b;
f[
1].x:=e[1].x;
f[
1].n:=1;
f[
1].r:=e[1].b-e[1].a;
while head<tail do
begin
inc(head);

i:
=f[head].n;
repeat
inc(i);
until ((f[head].x-e[i].x<=mh)and(e[i].a<=f[head].b)and(e[i].b>=f[head].b))or(i>n);

if i<=n then
begin
if e[i].x=0 then
begin
// if f[head].x+f[head].l<ans then ans:=f[head].x+f[head].l; 错误就在这里
if f[head].x+f[head].r<ans then ans:=f[head].x+f[head].r;
//continue;
end else
begin
inc(tail);
f[tail].a:
=e[i].a;
f[tail].b:
=e[i].b;
f[tail].n:
=i;
f[tail].x:
=e[i].x;
f[tail].l:
=f[head].r+f[head].x-e[i].x+f[head].b-e[i].a;
f[tail].r:
=f[head].r+f[head].x-e[i].x+e[i].b-f[head].b;
end;
end;

i:
=f[head].n;
repeat
inc(i);
until ((f[head].x-e[i].x<=mh)and(e[i].a<=f[head].a)and(e[i].b>=f[head].a))or(i>n);

if i<=n then
begin
if e[i].x=0 then
begin
if f[head].x+f[head].l<ans then ans:=f[head].x+f[head].l;
//if f[head].x+f[head].r<ans then ans:=f[head].x+f[head].r;还有这里
//continue;
end else
begin
inc(tail);
f[tail].a:
=e[i].a;
f[tail].b:
=e[i].b;
f[tail].n:
=i;
f[tail].x:
=e[i].x;
f[tail].l:
=f[head].l+f[head].x-e[i].x+f[head].a-e[i].a;
f[tail].r:
=f[head].l+f[head].x-e[i].x+e[i].b-f[head].a;
end;
end;
end;
if ans<>maxlongint then writeln(ans) else writeln('TP');
end.