题目描述
一个二叉树,树中每个节点的权值互不相同。
现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。
输入格式
第一行包含整数 NNN,表示二叉树的节点数。
第二行包含 NNN 个整数,表示二叉树的后序遍历。
第三行包含 NNN 个整数,表示二叉树的中序遍历。
输出格式
输出一行 NNN 个整数,表示二叉树的层序遍历。
数据范围
1≤N≤301≤N≤301≤N≤30
官方并未给出各节点权值的取值范围,为方便起见,在本网站范围取为 1∼N1∼N1∼N。
输入样例
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例
4 1 6 3 5 7 2
具体实现
#include
using namespace std;
const int N=35;
int n;
//a[N]表示后序遍历
//b[N]表示中序遍历
//p[N]存储在中序遍历中每一个数值的位置
int a[N],b[N],p[N];
//每一层开一个vector用来记录每一层的层序遍历
vectorlevel[N];
//传入a数组的起点和终点,b数组的起点和终点,d表示层数
void build(int al,int ar,int bl,int br,int d)
{if(al>ar){return ;}int val=a[ar]; //val表示根节点 level[d].push_back(val); int k=p[val]; //p[val]表示根节点在b数组中的位置 build(al,al+k-1-bl,bl,k-1,d+1); //左子树的中序遍历和后序遍历 build(al+k-bl,ar-1,k+1,br,d+1); //右子树的中序遍历和后序遍历
}
int main()
{cin>>n;for(int i=0;icin>>a[i];} for(int i=0;icin>>b[i];}for(int i=0;ip[b[i]]=i;}build(0,n-1,0,n-1,0);for(int i=0;ifor(int x: level[i]){cout<
题目描述
或许你并不知道,你的某个朋友是你的亲戚。
他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。
如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。
在这种情况下,最好的帮手就是计算机。
为了将问题简化,你将得到一些亲戚关系的信息,如 Marry 和 Tom 是亲戚,Tom 和 Ben 是亲戚,等等。
从这些信息中,你可以推出 Marry 和 Ben 是亲戚。
请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。
输入格式
输入由两部分组成。
第一部分以 N,MN,MN,M 开始。NNN 为问题涉及的人的个数。这些人的编号为 1,2,3,…,N1,2,3,…,N1,2,3,…,N。下面有 MMM 行,每行有两个数 ai,bia_{i},b_{i}ai,bi,表示已知 aia_{i}ai 和 bib_{i}bi 是亲戚。
第二部分以 QQQ 开始。以下 QQQ 行有 QQQ 个询问,每行为 ci,dic_{i},d_{i}ci,di,表示询问 cic_{i}ci 和 did_{i}di 是否为亲戚。
输出格式
对于每个询问 ci,dic_{i},d_{i}ci,di,输出一行:若 cic_{i}ci 和 did_{i}di 为亲戚,则输出 Yes
,否则输出 No
。
数据范围
1≤N≤200001≤N≤200001≤N≤20000
1≤M≤1061≤M≤10^{6}1≤M≤106
1≤Q≤1061≤Q≤10^{6}1≤Q≤106
输入样例
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9
输出样例
Yes
No
Yes
具体实现
#include
using namespace std;
const int N = 20010;
int n, m;
int p[N];
int find(int x)
{if (p[x] != x) p[x] = find(p[x]);return p[x];
}
int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++ ) p[i] = i;while (m -- ){int a, b;scanf("%d%d", &a, &b);p[find(a)] = find(b);}scanf("%d", &m);while (m -- ){int a, b;scanf("%d%d", &a, &b);if (find(a) == find(b)) puts("Yes");else puts("No");}return 0;
}
题目描述
奶牛贝茜正在学习如何在不同进制之间转换数字。
但是她总是犯错误,因为她无法轻易的用两个前蹄握住笔。
每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。
例如,如果她将数字 141414 转换为二进制数,那么正确的结果应为 111011101110,但她可能会写下 011001100110 或 111111111111。
贝茜不会额外添加或删除数字,但是可能会由于写错数字的原因,写下包含前导 000 的数字。
给定贝茜将数字 NNN 转换为二进制数字以及三进制数字的结果,请确定 NNN 的正确初始值(十进制表示)。
输入格式
第一行包含 NNN 的二进制表示,其中一位是错误的。
第二行包含 NNN 的三进制表示,其中一位是错误的。
输出格式
输出正确的 NNN 的值。
数据范围
0≤N≤1090≤N≤10^{9}0≤N≤109 ,且存在唯一解。
输入样例
1010
212
输出样例
14
样例解释
141414 在二进制下的正确表示为 111011101110,在三进制下的正确表示为 112112112。
具体实现
#include
using namespace std;
int base(string s,int b) //将b进制的数转换成10进制
{int res=0;for(int i=0;ires=res*b+s[i]-'0';}return res;
}
int main()
{//x是二进制表示的结果 //y是三进制表示的结果 string x,y; cin>>x>>y; unordered_sethash; for(int i=0;istring s=x;s[i]^=1; //0,1互相转换 if(s.size()>1&&s[0]=='0'){continue;}hash.insert(base(s,2));}for(int i=0;ifor(int j=0;j<3;j++){if(y[i]-'0'!=j){string s=y;s[i]=j+'0';// 0,1,2相互转换 if(s.size()>1&&s[0]=='0'){continue;}int n=base(s,3);if(hash.count(n)){cout<
题目描述
给定一个长度为 NNN 的序列 AAA,要求把该序列分成若干段,在满足每段中所有数的和不超过 MMM 的前提下,让每段中所有数的最大值之和最小。
试计算这个最小值。
输入格式
第一行包含两个整数 NNN 和 MMM。
第二行包含 NNN 个整数,表示完整的序列 AAA。
输出格式
输出一个整数,表示结果。
如果结果不存在,则输出 −1−1−1。
数据范围
0≤N≤1050≤N≤10^{5}0≤N≤105
0≤M≤10110≤M≤10^{11}0≤M≤1011
序列 AAA 中的数非负,且不超过 10610^{6}106。
输入样例
8 17
2 2 2 8 1 8 2 1
输出样例
12
具体实现
#include
#include
#include
#include using namespace std;typedef long long LL;const int N = 100010;int n;
LL m;
int w[N], q[N];
LL f[N];
multiset S;void remove(LL x)
{auto it = S.find(x);S.erase(it);
}int main()
{scanf("%d%lld", &n, &m);for (int i = 1; i <= n; i ++ ){scanf("%d", &w[i]);if (w[i] > m){puts("-1");return 0;}}int hh = 0, tt = -1;LL sum = 0;for (int i = 1, j = 1; i <= n; i ++ ){sum += w[i];while (sum > m){sum -= w[j ++ ];if (hh <= tt && q[hh] < j){if (hh < tt) remove(f[q[hh]] + w[q[hh + 1]]);hh ++ ;}}while (hh <= tt && w[q[tt]] <= w[i]){if (hh < tt) remove(f[q[tt - 1]] + w[q[tt]]);tt -- ;}q[ ++ tt] = i;if (hh < tt) S.insert(f[q[tt - 1]] + w[q[tt]]);f[i] = f[j - 1] + w[q[hh]];if (S.size()) f[i] = min(f[i], *S.begin());}printf("%lld\n", f[n]);return 0;
}
题目描述
一个字符串的前缀是从第一个字符开始的连续若干个字符,例如 abaab
共有 555 个前缀,分别是 a
,ab
,aba
,abaa
,abaab
。
我们希望知道一个 NNN 位字符串 SSS 的前缀是否具有循环节。
换言之,对于每一个从头开始的长度为 i(i>1)i(i>1)i(i>1)的前缀,是否由重复出现的子串 AAA 组成,即 AAA…AAAA…AAAA…A (AAA 重复出现 KKK 次,K>1K>1K>1)。
如果存在,请找出最短的循环节对应的 KKK 值(也就是这个前缀串的所有可能重复节中,最大的 KKK 值)。
输入格式
输入包括多组测试数据,每组测试数据包括两行。
第一行输入字符串 SSS 的长度 NNN。
第二行输入字符串 SSS。
输入数据以只包括一个 000 的行作为结尾。
输出格式
对于每组测试数据,第一行输出 Test case #
和测试数据的编号。
接下来的每一行,输出具有循环节的前缀的长度 iii 和其对应 KKK,中间用一个空格隔开。
前缀长度需要升序排列。
在每组测试数据的最后输出一个空行。
数据范围
2≤N≤10000002≤N≤10000002≤N≤1000000
输入样例
3
aaa
4
abcd
12
aabaabaabaab
0
输出样例
Test case #1
2 2
3 3
(空行)
Test case #2
(空行)
Test case #3
2 2
6 2
9 3
12 4
(空行)
具体实现
#include
using namespace std;
const int N = 1000010;
int n;
char s[N];
int ne[N];
int main()
{int T=1;while(scanf("%d",&n),n){scanf("%s",s+1);for(int i=2,j=0;i<=n;i++){while(j&&s[i]!=s[j+1]){j=ne[j];}if(s[i]==s[j+1]){j++ ;}ne[i]=j;}printf("Test case #%d\n",T);T++;for(int i=1;i<=n;i++){int t=i-ne[i];if(i%t==0&&i/t>1){printf("%d %d\n",i,i/t);} }puts("");}return 0;
}