2021GPLT全国总决赛华山论剑组_2021天梯赛省赛华山论剑组原题_MastErXZ-∞的博客-程序员秘密

技术标签: GPLT  c++  题解  acm竞赛  

前言

第一次真正意义上参加了国家级计算机竞赛,算法学得不多也不扎实。大一第二学期开设的数据结构和离散数学确是好课程,只是我没有好好学,不过STL帮我在偷鸡(懒得写算法)上帮了很大忙。比赛时的心态也不太好,脑子里全是不该想的(心中无女人,代码自然神就是句笑话)。

 

题目还写得不完备,相应的算法和结构刨着根了自然就全了。

you.come() ? rain.stop() : I.wait()

等你晴云雨

 

L1-1  人与神 (5 分)

 

跨界大神 L. Peter Deutsch 有一句名言:“To iterate is human, to recurse divine.”(迭代的是人,递归的是神)。本题就请你直接在屏幕上输出这句话。

输入格式:

本题没有输入。

输出格式:

在一行中输出 To iterate is human, to recurse divine.

输入样例:

输出样例:

To iterate is human, to recurse divine.

 

签到题。

#include<iostream>;
#include<bits/stdc++.h>
#include<algorithm> 
using namespace std;
int main(){
	cout<<"To iterate is human, to recurse divine.";
	return 0;
}

 

 

L1-2 两小时学完C语言 (5 分)

 

知乎上有个宝宝问:“两个小时内如何学完 C 语言?”当然,问的是“学完”并不是“学会”。

假设一本 C 语言教科书有 N 个字,这个宝宝每分钟能看 K 个字,看了 M 分钟。还剩多少字没有看?

输入格式:

输入在一行中给出 3 个正整数,分别是 N(不超过 400 000),教科书的总字数;K(不超过 3 000),是宝宝每分钟能看的字数;M(不超过 120),是宝宝看书的分钟数。

题目保证宝宝看完的字数不超过 N。

输出格式:

在一行中输出宝宝还没有看的字数。

输入样例:

100000 1000 72

输出样例:

28000

 

水。

#include<iostream>;
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
int main() {
	int n,k,m;
	cin>>n>>k>>m;
	cout<<n-k*m;
	return 0;
}

 

 

L1-3 强迫症 (10 分)

 

小强在统计一个小区里居民的出生年月,但是发现大家填写的生日格式不统一,例如有的人写 199808,有的人只写 9808。有强迫症的小强请你写个程序,把所有人的出生年月都整理成 年年年年-月月 格式。对于那些只写了年份后两位的信息,我们默认小于 22 都是 20 开头的,其他都是 19 开头的。

输入格式:

输入在一行中给出一个出生年月,为一个 6 位或者 4 位数,题目保证是 1000 年 1 月到 2021 年 12 月之间的合法年月。

输出格式:

在一行中按标准格式 年年年年-月月 将输入的信息整理输出。

输入样例 1:

9808

输出样例 1:

1998-08

输入样例 2:

0510

输出样例 2:

2005-10

输入样例 3:

196711

输出样例 3:

1967-11

 

水。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;

string s;

int main() {
	cin>>s;
	int year;
	int len=s.length() ;
	year=(s[0]-48)*10+(s[1]-48);
	if(len==4) {
		if(year<22) cout<<"20";
		else		cout<<"19";
		cout<<s[0]<<s[1]<<'-'<<s[2]<<s[3];
	} else {
		for(int i=0; i<4; i++)	cout<<s[i];
		cout<<'-';
		for(int i=4; i<6; i++)	cout<<s[i];
	}
	return 0;
}

 

 

 L1-4 降价提醒机器人 (10 分)

 

小 T 想买一个玩具很久了,但价格有些高,他打算等便宜些再买。但天天盯着购物网站很麻烦,请你帮小 T 写一个降价提醒机器人,当玩具的当前价格比他设定的价格便宜时发出提醒。

输入格式:

输入第一行是两个正整数 N 和 M (1≤N≤100,0≤M≤1000),表示有 N 条价格记录,小 T 设置的价格为 M。

接下来 N 行,每行有一个实数 P​i​​(−1000.0<P​i​​<1000.0),表示一条价格记录。

输出格式:

对每一条比设定价格 M 便宜的价格记录 P,在一行中输出 On Sale! P,其中 P 输出到小数点后 1 位。

输入样例:

4 99
98.0
97.0
100.2
98.9

输出样例:

On Sale! 98.0
On Sale! 97.0
On Sale! 98.9

 

水。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;

int main() {
	int n;
	double m,num;
	cin>>n>>m;
	while(n--) {
		cin>>num;
		if(num<m) {
			cout<<"On Sale! ";
			printf("%.1lf\n",num);
		}
	}
	return 0;
}

 

 

L1-5 大笨钟的心情 (15 分)

 

心情.jpg

 

有网友问:未来还会有更多大笨钟题吗?笨钟回复说:看心情……

本题就请你替大笨钟写一个程序,根据心情自动输出回答。

输入格式:

输入在一行中给出 24 个 [0, 100] 区间内的整数,依次代表大笨钟在一天 24 小时中,每个小时的心情指数。

随后若干行,每行给出一个 [0, 23] 之间的整数,代表网友询问笨钟这个问题的时间点。当出现非法的时间点时,表示输入结束,这个非法输入不要处理。题目保证至少有 1 次询问。

输出格式:

对每一次提问,如果当时笨钟的心情指数大于 50,就在一行中输出 心情指数 Yes,否则输出 心情指数 No

输入样例:

80 75 60 50 20 20 20 20 55 62 66 51 42 33 47 58 67 52 41 20 35 49 50 63
17
7
3
15
-1

输出样例:

52 Yes
20 No
50 No
58 Yes

 

小小判断一下。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;

int lis[24];
int num;

int main() {
	for(int i=0; i<24; i++)	cin>>lis[i];
	while(1) {
		cin>>num;
		if(num>=0&&num<=23) {
			cout<<lis[num]<<' ';
			lis[num]>50?cout<<"Yes":cout<<"No";
			cout<<endl;
		} else	break;
	}
	return 0;
}

 

 

L1-6 吉老师的回归 (15 分)

 

曾经在天梯赛大杀四方的吉老师决定回归天梯赛赛场啦!

为了简化题目,我们不妨假设天梯赛的每道题目可以用一个不超过 500 的、只包括可打印符号的字符串描述出来,如:Problem A: Print "Hello world!"

众所周知,吉老师的竞赛水平非常高超,你可以认为他每道题目都会做(事实上也是……)。因此,吉老师会按照顺序看题并做题。但吉老师水平太高了,所以签到题他就懒得做了(浪费时间),具体来说,假如题目的字符串里有 qiandao 或者 easy(区分大小写)的话,吉老师看完题目就会跳过这道题目不做。

现在给定这次天梯赛总共有几道题目以及吉老师已经做完了几道题目,请你告诉大家吉老师现在正在做哪个题,或者吉老师已经把所有他打算做的题目做完了。

提醒:天梯赛有分数升级的规则,如果不做签到题可能导致团队总分不足以升级,一般的选手请千万不要学习吉老师的酷炫行为!

输入格式:

输入第一行是两个正整数 N,M (1≤M≤N≤30),表示本次天梯赛有 N 道题目,吉老师现在做完了 M 道。

接下来 N 行,每行是一个符合题目描述的字符串,表示天梯赛的题目内容。吉老师会按照给出的顺序看题——第一行就是吉老师看的第一道题,第二行就是第二道,以此类推。

输出格式:

在一行中输出吉老师当前正在做的题目对应的题面(即做完了 M 道题目后,吉老师正在做哪个题)。如果吉老师已经把所有他打算做的题目做完了,输出一行 Wo AK le

输入样例 1:

5 1
L1-1 is a qiandao problem.
L1-2 is so...easy.
L1-3 is Easy.
L1-4 is qianDao.
Wow, such L1-5, so easy.

输出样例 1:

L1-4 is qianDao.

输入样例 2:

5 4
L1-1 is a-qiandao problem.
L1-2 is so easy.
L1-3 is Easy.
L1-4 is qianDao.
Wow, such L1-5, so!!easy.

输出样例 2:

Wo AK le

 

STL真好用,不用手写KMP算法。

PS:不过python更BUG,直接判断(in) 。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;

string qd="qiandao";
string ez="easy";

string::iterator it1,it2;

int n,m,cnt;

struct {
	string name;
} lis[35];

int main() {
	cin>>n>>m;
	getchar();
	for(int i=0; i<n; i++) {
		getline(cin,lis[i].name);
	}
	for(int i=0; i<n; i++) {
		it1=search(lis[i].name.begin() ,lis[i].name.end(),qd.begin() ,qd.end() );
		it2=search(lis[i].name.begin() ,lis[i].name.end(),ez.begin() ,ez.end() );
		if(it1==lis[i].name.end() &&it2==lis[i].name.end() ) {
			cnt++;
		}
		if(cnt==m)	{
			i++;
			while(i<n) {
				it1=search(lis[i].name.begin() ,lis[i].name.end(),qd.begin() ,qd.end() );
				it2=search(lis[i].name.begin() ,lis[i].name.end(),ez.begin() ,ez.end() );
				if(it1==lis[i].name.end() &&it2==lis[i].name.end() ) {
					cout<<lis[i].name;
					return 0;
				}
				i++;
			}
		}
	}
	cout<<"Wo AK le";
	return 0;
}

 

 

L1-7 天梯赛的善良 (20 分)

 

天梯赛是个善良的比赛。善良的命题组希望将题目难度控制在一个范围内,使得每个参赛的学生都有能做出来的题目,并且最厉害的学生也要非常努力才有可能得到高分。

于是命题组首先将编程能力划分成了 10​6​​ 个等级(太疯狂了,这是假的),然后调查了每个参赛学生的编程能力。现在请你写个程序找出所有参赛学生的最小和最大能力值,给命题组作为出题的参考。

输入格式:

输入在第一行中给出一个正整数 N(≤2×10​4​​),即参赛学生的总数。随后一行给出 N 个不超过 10​6​​ 的正整数,是参赛学生的能力值。

输出格式:

第一行输出所有参赛学生的最小能力值,以及具有这个能力值的学生人数。第二行输出所有参赛学生的最大能力值,以及具有这个能力值的学生人数。同行数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

10
86 75 233 888 666 75 886 888 75 666

输出样例:

75 3
888 2

 

STL函数。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm> 
#include<vector>
using namespace std;

typedef long long ll;

ll n,m;
vector<ll>s;
ll lis[20020];
ll ans;
int  main(){
	ll n;
	cin>>n;
	for(ll i=0;i<n;i++)	cin>>lis[i];
	ans=*min_element(lis,lis+n);
	cout<<ans<<' '<<count(lis,lis+n,ans)<<endl;
	ans=*max_element(lis,lis+n);
	cout<<ans<<' '<<count(lis,lis+n,ans);
	return 0;
}

 

 

L1-8 乘法口诀数列 (20 分)

 

本题要求你从任意给定的两个 1 位数字 a​1​​ 和 a​2​​ 开始,用乘法口诀生成一个数列 {a​n​​},规则为从 a​1​​ 开始顺次进行,每次将当前数字与后面一个数字相乘,将结果贴在数列末尾。如果结果不是 1 位数,则其每一位都应成为数列的一项。

输入格式:

输入在一行中给出 3 个整数,依次为 a​1​​、a​2​​ 和 n,满足 0≤a​1​​,a​2​​≤9,0<n≤10​3​​。

输出格式:

在一行中输出数列的前 n 项。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

2 3 10

输出样例:

2 3 6 1 8 6 8 4 8 4

样例解释:

数列前 2 项为 2 和 3。从 2 开始,因为 2×3=6,所以第 3 项是 6。因为 3×6=18,所以第 4、5 项分别是 1、8。依次类推…… 最后因为第 6 项有 6×8=48,对应第 10、11 项应该是 4、8。而因为只要求输出前 10 项,所以在输出 4 后结束。

 

STL模拟,动态数组大小有n就行了。

每次取容器尾的两个数字相加,按位放入。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm> 
#include<vector>
using namespace std;
typedef long long ll;

vector<int>s;

int main(){
	int a1,a2;
	unsigned int n;
	cin>>a1>>a2>>n;
	s.push_back(a1);
	s.push_back(a2);
	int len=s.size() ;
	int it=0;
	while(s.size()<=n){
		int c=s[it]*s[it+1];
		char t[100];
		sprintf(t,"%d",c);
		for(int i=0;t[i];i++)	s.push_back(t[i]-48);
		len=s.size() ;
		it++;
	}
	for(int i=0;i<n;i++){
		cout<<s[i];
		if(i!=n-1)	cout<<' ';
	}
	return 0;
}

 

 

L2-1 包装机 (25 分)

 

一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。

图1.JPG

图1 自动包装机的结构

图2.JPG

图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态

一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。

现给定一系列按钮操作,请你依次列出流水线上的物品。

输入格式:

输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 S​max​​(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。

最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。

输出格式:

在一行中顺序输出流水线上的物品,不得有任何空格。

输入样例:

3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1

输出样例:

MATA

 

模拟,STL。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;

ll n,m;
unsigned long long maxn;
ll flag;
char c;

struct {
	int pos=0;
	string gui;
} lis[105];

stack<char> s;
vector<char> ans;

int main() {
	cin>>n>>m>>maxn;
	for(ll i=1; i<=n; i++) {
		lis[i].pos=0;
		cin>>lis[i].gui;
	}
	
	cin>>flag;
	while(flag!=-1) {
		if(flag==0) {
			if(s.size() !=0) {
				ans.push_back(s.top() ) ;
				s.pop() ;
			}
		} else {
			if(lis[flag].pos<m) {
				c=lis[flag].gui[lis[flag].pos++];
				if(s.size() >=maxn) {
					ans.push_back(s.top() ) ;
					s.pop() ;
					s.push(c) ;
				} else {
					s.push(c) ;
				}
			}
		}
		cin>>flag;
	}
	
	for(auto &it:ans)	cout<<it;
	
	return 0;
}

 

 

L2-2 病毒溯源 (25 分)

 

V.JPG

病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。

现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。

在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。

输入格式:

输入在第一行中给出一个正整数 N(≤10​4​​),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。

随后 N 行,每行按以下格式描述一种病毒的变异情况:

k 变异株1 …… 变异株k

其中 k 是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。

输出格式:

首先输出从源头开始最长变异链的长度。

在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。

注:我们称序列 { a​1​​,⋯,a​n​​ } 比序列 { b​1​​,⋯,b​n​​ } “小”,如果存在 1≤k≤n 满足 a​i​​=b​i​​ 对所有 i<k 成立,且 a​k​​<b​k​​。

输入样例:

10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1

输出样例:

4
0 4 9 1

 

树形结构,有思路,但敲不出来。

等我想明白了填坑。

 

 

L2-3 清点代码库 (25 分)

 

code.jpg

上图转自新浪微博:“阿里代码库有几亿行代码,但其中有很多功能重复的代码,比如单单快排就被重写了几百遍。请设计一个程序,能够将代码库中所有功能重复的代码找出。各位大佬有啥想法,我当时就懵了,然后就挂了。。。”

这里我们把问题简化一下:首先假设两个功能模块如果接受同样的输入,总是给出同样的输出,则它们就是功能重复的;其次我们把每个模块的输出都简化为一个整数(在 int 范围内)。于是我们可以设计一系列输入,检查所有功能模块的对应输出,从而查出功能重复的代码。你的任务就是设计并实现这个简化问题的解决方案。

输入格式:

输入在第一行中给出 2 个正整数,依次为 N(≤10​4​​)和 M(≤10​2​​),对应功能模块的个数和系列测试输入的个数。

随后 N 行,每行给出一个功能模块的 M 个对应输出,数字间以空格分隔。

输出格式:

首先在第一行输出不同功能的个数 K。随后 K 行,每行给出具有这个功能的模块的个数,以及这个功能的对应输出。数字间以 1 个空格分隔,行首尾不得有多余空格。输出首先按模块个数非递增顺序,如果有并列,则按输出序列的递增序给出。

注:所谓数列 { A​1​​, ..., A​M​​ } 比 { B​1​​, ..., B​M​​ } 大,是指存在 1≤i<M,使得 A​1​​=B​1​​,...,A​i​​=B​i​​ 成立,且 A​i+1​​>B​i+1​​。

输入样例:

7 3
35 28 74
-1 -1 22
28 74 35
-1 -1 22
11 66 0
35 28 74
35 28 74

输出样例:

4
3 35 28 74
2 -1 -1 22
1 11 66 0
1 28 74 35

 

统计与排序,stl很方便。

第一次重构cmp时按输出排序,最后一例不过,遂改成逐个比对(输出序列递增?(大雾 ))。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<string>
using namespace std;
typedef long long ll;

ll read() {
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-')	f=-1;
		c=getchar();
	}
	while(isdigit(c))	x=x*10+(c-48),c=getchar();
	return x*f;
}

typedef struct {
	vector<ll>sc;
	ll cnt;
} TYPELIS;

vector<ll>t[10010];
ll num;
map<vector<ll>,int>mp;

/*
bool cmp(TYPELIS a,TYPELIS b) {
	if(a.cnt==b.cnt)	return a.sc[a.sc.size()-1]<b.sc[b.sc.size()-1];
	return a.cnt>b.cnt;
}
*/

bool cmp(TYPELIS a,TYPELIS b) {
	if(a.cnt==b.cnt) {
		for(unsigned  int i=0; i<a.sc.size() ; i++) {
			if(a.sc[i]==b.sc[i])	continue;
			return a.sc[i]<b.sc[i];
		}
	}
	return a.cnt>b.cnt;
}

ll n,m;

int main() {
	
	n=read();
	m=read();
	TYPELIS lis[n+10];
	
	for(ll i=0; i<n; i++) {
		for(ll j=0; j<m; j++) {
			num=read();
			t[i].push_back(num) ;
		}
		mp[t[i]]++;
	}

	ll len=0;
	for(auto &it:mp) {
		lis[len].sc=it.first;
		lis[len].cnt=it.second;
		len++;
	}

	cout<<len<<endl;

	sort(lis,lis+len,cmp);

	for(ll i=0; i<len; i++) {
		cout<<lis[i].cnt<<' ';
		int len=lis[i].sc.size();
		for(ll j=0; j<len; j++) {
			cout<<lis[i].sc[j];
			if(j!=len-1)	cout<<' ';
		}
		cout<<endl;
	}

	return 0;
}

 

L2-4 哲哲打游戏 (25 分)

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切!

为简化模型,我们不妨假设游戏有 N 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另外一个剧情点。此外,游戏还设置了一些存档,在某个剧情点可以将玩家的游戏进度保存在一个档位上,读取存档后可以回到剧情点,重新进行操作或者选择,到达不同的剧情点。

为了追踪硬核游戏玩家哲哲的攻略进度,你打算写一个程序来完成这个工作。假设你已经知道了游戏的全部剧情点和流程,以及哲哲的游戏操作,请你输出哲哲的游戏进度。

输入格式:

输入第一行是两个正整数 N 和 M (1≤N,M≤10​5​​),表示总共有 N 个剧情点,哲哲有 M 个游戏操作。

接下来的 N 行,每行对应一个剧情点的发展设定。第 i 行的第一个数字是 K​i​​,表示剧情点 i 通过一些操作或选择能去往下面 K​i​​ 个剧情点;接下来有 K​i​​ 个数字,第 k 个数字表示做第 k 个操作或选择可以去往的剧情点编号。

最后有 M 行,每行第一个数字是 0、1 或 2,分别表示:

  • 0 表示哲哲做出了某个操作或选择,后面紧接着一个数字 j,表示哲哲在当前剧情点做出了第 j 个选择。我们保证哲哲的选择永远是合法的。
  • 1 表示哲哲进行了一次存档,后面紧接着是一个数字 j,表示存档放在了第 j 个档位上。
  • 2 表示哲哲进行了一次读取存档的操作,后面紧接着是一个数字 j,表示读取了放在第 j 个位置的存档。

约定:所有操作或选择以及剧情点编号都从 1 号开始。存档的档位不超过 100 个,编号也从 1 开始。游戏默认从 1 号剧情点开始。总的选项数(即 ∑K​i​​)不超过 10​6​​。

输出格式:

对于每个 1(即存档)操作,在一行中输出存档的剧情点编号。

最后一行输出哲哲最后到达的剧情点编号。

输入样例:

10 11
3 2 3 4
1 6
3 4 7 5
1 3
1 9
2 3 5
3 1 8 5
1 9
2 8 10
0
1 1
0 3
0 1
1 2
0 2
0 2
2 2
0 3
0 1
1 1
0 2

输出样例:

1
3
9
10

样例解释:

简单给出样例中经过的剧情点顺序:

1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10。

档位 1 开始存的是 1 号剧情点;档位 2 存的是 3 号剧情点;档位 1 后来又存了 9 号剧情点。

 

纯模拟,第一次参加GPLT,把此题看成图论直接跳过了。补题时仔细一看才发现是纯模拟,痛失国三。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<string>
#include<stack>
#include<map>
#include<list>
#include<vector>
#include<queue>
#include<deque>
#include<set>
#include<functional>
#define pi 3.14159265358979323846264338327950288419716939937510582097494
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

ll read() {
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-')	f=-1;
		c=getchar();
	}
	while(isdigit(c))	x=x*10+(c-48),c=getchar();
	return x*f;
}

ull n,m;
ull temp1,temp2,now=1;

int main() {
	cin>>n>>m;
	vector<ull>lis[n+10];
	map<ull,ull>data;

	for(ull i=1; i<=n; i++) {
		temp1=read();
		lis[i].push_back(temp1) ;
		while(temp1--) {
			temp2=read();
			lis[i].push_back(temp2) ;
		}
	}

	while(m--) {
		temp1=read();
		temp2=read();
		switch(temp1) {
			case 0: {
				now=lis[now][temp2];
				break;
			}
			case 1: {
				data[temp2]=now;
				cout<<now<<endl;
				break;
			}
			case 2: {
				now=data[temp2];
				break;
			}
		}
	}

	cout<<now;

	return 0;
}
/*
 2 3 4
 6
 4 7 5
 3
 9
 3 5
 1 8 5
 9
 8 10


0 操作
1 存档于
2 读档

档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
9 3

step	change	now
1 1				1
0 3		1 3		4
0 1		4 1		3
1 2				3
0 2		3 2		7
0 2		7 2		8
2 2				3
0 3		3 3		5
0 1		5 1		9
1 1				1
0 2		9 2		10
*/

 

L3-2 还原文件 (30 分)

一份重要文件被撕成两半,其中一半还被送进了碎纸机。我们将碎纸机里找到的纸条进行编号,如图 1 所示。然后根据断口的折线形状跟没有切碎的半张纸进行匹配,最后还原成图 2 的样子。要求你输出还原后纸条的正确拼接顺序。

file1.JPG

图1 纸条编号

file2.JPG

图2 还原结果

输入格式:

输入首先在第一行中给出一个正整数 N(1<N≤10​5​​),为没有切碎的半张纸上断口折线角点的个数;随后一行给出从左到右 N 个折线角点的高度值(均为不超过 100 的非负整数)。

随后一行给出一个正整数 M(≤100),为碎纸机里的纸条数量。接下去有 M 行,其中第 i 行给出编号为 i(1≤i≤M)的纸条的断口信息,格式为:

K h[1] h[2] ... h[K]

其中 K 是断口折线角点的个数(不超过 10​4​​+1),后面是从左到右 K 个折线角点的高度值。为简单起见,这个“高度”跟没有切碎的半张纸上断口折线角点的高度是一致的。

输出格式:

在一行中输出还原后纸条的正确拼接顺序。纸条编号间以一个空格分隔,行首尾不得有多余空格。

题目数据保证存在唯一解。

输入样例:

17
95 70 80 97 97 68 58 58 80 72 88 81 81 68 68 60 80
6
4 68 58 58 80
3 81 68 68
3 95 70 80
3 68 60 80
5 80 72 88 81 81
4 80 97 97 68

输出样例:

3 6 1 5 2 4

 

用string里的.find()加sort()能拿26,目前没能全AC暂时留坑。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/masterxzpro/article/details/116324436

智能推荐

SpringBoot学习记录(十三)-------- SpringBoot启动报错Failed to auto configure default logger context及解决方法_手写的从前98的博客-程序员秘密

报错内容:Failed to auto configure default logger contextReported exception:ch.qos.logback.core.joran.spi.JoranException: I/O error occurred while parsing xml file at ch.qos.logback.core.joran.event.Sa...

Python Excel操作模块XlsxWriter之写入日期worksheet.write_datetime()_xlsxwriter 日期_AuserBB的博客-程序员秘密

worksheet.write_datetime()write_datetime(row, col, datetime[, cell_format])向工作表单元格写入日期或时间。参数:row(int) - 单元格所在的行(索引从0开始计数)。col(int) - 单元格所在的列(索引从0开始计数)。datetime(datetime) - datetime.datetime, .date, .t...

position和transform的用法_position transform_新参者-tangent的博客-程序员秘密

POSITIONCSS中我们想要改变一个元素的位置,我们可以采用的方法之一就是定位,这也是我们最先接触的方法。其主要用法就是给需要移动的元素的父元素或以上添加 position:relative; 再给自身添加 position:absolute; 然后通过改变方位(top,left,right,bottom)来实现元素的移动。TRANSFORMCSS3中提供了transform属性,其中的translateX和translateY值可以实现元素的横向与纵向移动。区别和选择经过测试。TRANSFO

centos安装openJDK1.8_chiyunyi2612的博客-程序员秘密

只要写到大版本即可,然后回自动安装该大版本下的最新的小版本 比如现在最新的小版本是212 那么安装完后的版本将是1.8.0_212 yum install -y java-1.8.0-openjdk 安装成功后,执行 java -version将输出如下以openjdk开头的版本信息 ...

UE4 Hair Strands浅析_cosserat rod_kuangben2000的博客-程序员秘密

=============UE4 Hair Strands浅析https://zhuanlan.zhihu.com/p/128669105UE4.24 Hair Strands浅析UE4.24推出了次世代发丝(Hair Strands)系统Groom,其实现大量参考了寒霜在Siggraph2019 Advances in Real-Time Rendering in Games course上的演讲。 Strand-based Hair Rendering in Frostbite在写这篇文章

HTML5新增加的功能_weixin_30955341的博客-程序员秘密

1、部分代码代替了以前的代码 例如:获取焦点 旧:document.getElementById("price");.focus; 新:&lt;input type="text" autofocus name="price" /&gt;2、使用HTML5之前,要表达一个文档的结构,只能通过&lt;div&gt;来实现;在HTMl5...

随便推点

BurpSuite的使用教程(下)_afei00123的博客-程序员秘密

5.Repeater(中继器/重放)功能模块 Repeater是用于手动操作和发送个别HTTP请求,并分析应用程序的响应一个简单的工具。可以发送一个内部请求从Burp任何地方到Repeater,修改请求并且发送。afei 可以从Proxy history、site map、Scanner等模块中右键菜单send to repeater发送到repeate...

什么是卷积_卷积符号_要什么自行车儿的博客-程序员秘密

此文章简单讲解了卷积是什么、卷积为什么这么厉害、卷积神经网络是什么。

布局优化?应该这么玩_kailaisi的博客-程序员秘密

布局优化?应该这么玩布局优化作为Android性能优化的一部分,其重要性不言而喻。那么在开发过程中,应该注意哪些事项,才能有助于我们开发出流畅的安卓应用?当遇到布局卡顿的时候,又该如何通过分析定位问题?本篇文章将会从原理到实践,一步步教你如何玩转布局优化。概念合理的布局,能够有效地提高性能,加快页面的显示速度,简化逻辑的复杂度。而布局对于Android性能的影响,则主要包含两个方面:测量+绘制。作用通过布局的优化,有效的减少页面的卡顿、丢帧等情况,实现应用的流畅。基础知识为什么布局复杂的时候

启动ZooKeeper出错及解决方法_小天努力学java的博客-程序员秘密

在搭建完ZooKeeper环境后,启动报错。找出问题后,解决了,做此记录:授人以鱼不如授人以渔!截图中已经讲的很详细,最重要的是使用:./zkServer.sh start-foreground发现问题解决问题问题所在:创建的myid文件没有在dataDir目录下,看截图: 附上最后stat没有选举出leader的原因: This ZooKeeper i...

密码经常忘记?三款软件能帮你看到电脑上保存的星号密码_电脑软件已保存密码 但是忘了_明金同学的博客-程序员秘密

很多时候,我们经常使用浏览器浏览各大网站,一般登录的时候都喜欢用浏览器记住密码功能直接保存在浏览器,随着时间的推移,记住的密码太多了一时之间记不起来了怎么办?针对以下三种场景拿出了珍藏多年的看家看家法宝。1. 查看WiFi密码有时候朋友来家里做客,问我们WIFI密码是多少?但我们貌似忘记WiFi密码了,这时候就需要它了,只有100K,无需安装,解压后双击打开能看到所有连接过的WiFi名称和密码。有了它,就算遇到已经连接过WiFi新电脑,只需双击点开它,立刻就能找到当前WiFi的密.

css数字固定居中怎么使用,css在盒子中垂直居中和固定居中_赫鑫磊的博客-程序员秘密

顶部固定居中我是固定的.w960{width: 960px;margin:0 auto;}.fixed{position: absolute;top:0;left: 0;right: 0;height: 90px;background: #ececec;}垂直居中ssss#box {width: 600px;height: 500px;position: relative;border: 1px ...

推荐文章

热门文章

相关标签