尼伯龙根之歌
【故事背景】
北欧「末世神话」中,火神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 黎明与三色虹桥
【题目背景】
『恶魔收敛了漆黑邪恶的羽翼
在天使面前温柔地保持安静
牧师拥抱祭坛断续祈祷
不停询问与阿斯嘉特还有多少距离。』
我认为也只有这道题最水 了,求逆序对
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 仍然纠结了我很长的时间,原因就是在更新状态的时候多了一点东西...
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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.