A - Koxia and Permutation
Reve has two integers n and k.
Let p be a permutation of length n. Let c be an array of length n - k + 1n−k+1 such that
Ci = max(pi, \dots, p_{i+k-1}) + \min(p_i, \dots, p_{i+k-1}).ci=max(pi,…,pi+k−1)+min(pi,…,pi+k−1).Let the cost of the permutation pp be the maximum element of cc.
Koxia wants you to construct a permutation with the minimum possible cost.
^\dagger† A permutation of length nn is an array consisting of nn distinct integers from 11 to nn in arbitrary order. For example, [2,3,1,5,4][2,3,1,5,4] is a permutation, but [1,2,2][1,2,2] is not a permutation (22 appears twice in the array), and [1,3,4][1,3,4] is also not a permutation (n=3n=3 but there is 44 in the array).
Input
Each test consists of multiple test cases. The first line contains a single integer tt (1 \leq t \leq 20001≤t≤2000) — the number of test cases. The description of test cases follows.
The first line of each test case contains two integers nn and kk (1 \leq k \leq n \leq 2 \cdot 10^51≤k≤n≤2⋅105).
It is guaranteed that the sum of nn over all test cases does not exceed 2 \cdot 10^52⋅105.
Output
For each test case, output nn integers p_1,p_2,\dots,p_np1,p2,…,pn, which is a permutation with minimal cost. If there is more than one permutation with minimal cost, you may output any of them.
Sample 1
Inputcopy | Outputcopy |
3 5 3 5 1 6 6 | 5 1 2 3 4 1 2 3 4 5 3 2 4 1 6 5 |
Note
In the first test case,
c_1 = \max(p_1,p_2,p_3) + \min(p_1,p_2,p_3) = 5 + 1 = 6c1=max(p1,p2,p3)+min(p1,p2,p3)=5+1=6.
c_2 = \max(p_2,p_3,p_4) + \min(p_2,p_3,p_4) = 3 + 1 = 4c2=max(p2,p3,p4)+min(p2,p3,p4)=3+1=4.
c_3 = \max(p_3,p_4,p_5) + \min(p_3,p_4,p_5) = 4 + 2 = 6c3=max(p3,p4,p5)+min(p3,p4,p5)=4+2=6.
Therefore, the cost is \max(6,4,6)=6max(6,4,6)=6. It can be proven that this is the minimal cost.
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k;
scanf("%d %d",&n,&k);
for(int i=1;i<=n/2;i++)
printf("%d %d ",n-i+1,i);
if(n%2!=0)
printf("%d ",n/2+1);
printf("\n");
}
}
执着把一个题目复杂化,其实只需要把数列按n,1,n-1,2……排列就是最优解。
二叉树的遍历
二叉树的四种遍历方式
前序遍历:先访问一棵树的根节点,再访问左子树,最后访问右子树。
中序遍历:先访问一棵树的左子树,再访问根节点,最后访问右子树。
后序遍历:先访问一棵树的左子树,再访问右子树,最后访问根节点。
层序遍历:首先访问第一层的根结点,然后从左到右访问第2层上的节点,接着访问第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
![](https://img-blog.csdnimg.cn/img_convert/9b8aa6e234f74d3edba8c08bf3db1ddf.png)
前序遍历:A B D NULL NULL NULL C E NULL NULL F NULL NULL
中序遍历:NULL D NULL B NULL A NULL E NULL C NULL F NULL
后序遍历:NULL NULL D NULL B NULL NULL E NULL NULL F C A
层序遍历:A B C D NULL E F NULL NULL NULL NULL NULL NULL
P1827 [USACO3.4] 美国血统 American Heritage
题目描述
农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。
你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:
C
/ \
/ \
B G
/ \ /
A D H
/ \
E F
树的中序遍历是按照左子树,根,右子树的顺序访问节点。
树的前序遍历是按照根,左子树,右子树的顺序访问节点。
树的后序遍历是按照左子树,右子树,根的顺序访问节点。
输入格式
第一行: 树的中序遍历
第二行: 同样的树的前序遍历
输出格式
单独的一行表示该树的后序遍历。
输入输出样例
输入 #1
ABEDFCHG
CBADEFGH
输出 #1
AEFDBHGC
#include<stdio.h>
#include<string.h>
char mid[30],fro[30],aft[30];
int len,n;
void dfs(int l,int r,int l1)
{
if (l==r)
{
aft[n++]=mid[l];
return ;
}
for (int i=l;i<=r;i++)//寻找根节点
if (mid[i]==fro[l1])
{
dfs(l,i-1,l1+1);//先累加左子树
dfs(i+1,r,l1+i-l+1);//后累加右子树
aft[n++]=mid[i];
break;
}
}
int main()
{
scanf("%s %s",mid,fro);
len=strlen(mid);
dfs(0,len-1,0);
printf("%s",aft);
}
这个题目写了一天😩。知道二叉树的遍历之后,根据前序和中序可以确定后序。首先,前序第一个C即为根结点,而中序根结点把整个字符串分成了左子树ABEDF和右子树HG。再继续可知前序根结点后一位就是根结点的左孩子B,B又把左子树这一部分分成了左A和右EDF。在中序A之后就是D,可知D就是EF的父结点……这样可以得到整个二叉树。
参考了别人的写法,我才勉强写出来了这个递归函数。分为前序和后序,l和r是记录左右子树的范围,l1是每个结点的位置,因为后序是左右根,所以先累加左边,再累加右边,最后还要加上根结点。