7-1 二叉树最长路径 (100 分)
给定一棵二叉树T,求T中的最长路径的长度,并输出此路径上各结点的值。若有多条最长路径,输出最右侧的那条。
输入格式:
第1行,1个整数n,表示二叉树有n个结点, 1≤n≤100000.
第2行,2n+1个整数,用空格分隔,表示T的扩展先根序列, -1表示空指针,结点用编号1到n表示。
输出格式:
第1行,1个整数length,length表示T中的最长路径的长度。
第2行,length+1个整数,用空格分隔,表示最右侧的最长路径。
输入样例:
在这里给出一组输入。例如:
5
1 2 -1 -1 3 4 -1 -1 5 -1 -1
输出样例:
在这里给出相应的输出。例如:
2
1 3 5
作者
谷方明
单位
吉林大学
代码长度限制
16 KB
时间限制
100 ms
内存限制
5 M
#include<iostream>
using namespace std;
int b[100000]; int q;
typedef struct bintree{
int data;
struct bintree* left;
struct bintree* right;
int height;
}*Bintree;
void CBT(Bintree& t){
int a;
cin>>a;
if(a==-1){
t=NULL;
return;
}
else{
t=(Bintree)malloc(sizeof(struct bintree));
t->data=a;
}
CBT(t->left);
CBT(t->right);
}
int GetHeight( Bintree t ){
if(!t) return -1;
if(t)
{
return t->height = 1+max(GetHeight(t->left),GetHeight(t->right));
}
}
void path(Bintree t){
GetHeight(t);
Bintree p=t;
while(p){
b[q++]=p->data;
if(!p->right||p->left&&p->right&&p->left->height>p->right->height)
p=p->left;
else p=p->right;
}
}
int main(){
int n;
Bintree t;
scanf("%d",&n);
CBT(t);
printf("%d\n",GetHeight(t));
path(t);
printf("%d",b[0]);
for(int i=1;i<q;i++)
printf(" %d",b[i]);
}
我的思路:
这道题没有什么难度,唯一需要注意的一点是要将每个节点的height值存起来,否则在求路径的时候会增加时间复杂度!!
7-2 森林的层次遍历 (100 分)
给定一个森林F,求F的层次遍历序列。森林由其先根序列及序列中每个结点的度给出。
输入格式:
第1行,1个整数n,表示森林的结点个数, 1≤n≤100000.
第2行,n个字符,用空格分隔,表示森林F的先根序列。字符为大小写字母及数字。
第3行,n个整数,用空格分隔,表示森林F的先根序列中每个结点对应的度。
输出格式:
1行,n个字符,用空格分隔,表示森林F的层次遍历序列。
输入样例:
在这里给出一组输入。例如:
14
A B C D E F G H I J K L M N
4 0 3 0 0 0 0 2 2 0 0 0 1 0
输出样例:
在这里给出相应的输出。例如:
A M B C G H N D E F I L J K
作者
谷方明
单位
吉林大学
代码长度限制
16 KB
时间限制
100 ms
内存限制
#include<bits/stdc++.h>
using namespace std;
vector<int>Son[100010];
char lsq[100010];
int degree[100010];
int pos=0;
queue<int>q;
int n;
int Createtree(){
int num=++pos;
for(int i=1;i<=degree[num];++i)
Son[num].push_back(Createtree());
return num;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int i,j;
cin>>n;
for(i=1;i<=n;i++)
cin>>lsq[i];
for(i=1;i<=n;i++)
cin>>degree[i];
while(pos!=n)
q.push(Createtree());
int root;
while(!q.empty()){
root=q.front();
q.pop();
cout<<lsq[root];
for(int j=0;j<degree[root];j++)
q.push(Son[root].at(j));
if(q.empty()==1) cout<<endl;
else cout<<" ";
}
}
我的思路;
(这个题我是看了同学们的代码才会的。)就是用容器套容器的方法存储一个节点的儿子节点(用下标表示),用一个辅助队列来进行层序遍历,具体实现的话就是用递归的思想,(炫辰已经说的很明白了)。然后注意,这个递归建树的函数返回的值其实就是森林的根节点,首先将这些根节点入队,之后再层序遍历。
7-3 纸带切割 (100 分)
有一条细长的纸带,长度为 L 个单位,宽度为一个单位。现在要将纸带切割成 n 段。每次切割把当前纸带分成两段,切割位置都在整数单位上,切割代价是当前切割纸带的总长度。每次切割都选择未达最终要求的最长纸带切割,若这样的纸带有多条,则任选一条切割。如何切割,才能完成任务,并且总代价最小。
输入格式:
第1行,1个整数n,表示切割成的段数, 1≤n≤100000.
第2行,n个整数Li,用空格分隔,表示要切割成的各段的长度,1≤Li≤200000000,1≤i≤n.
输出格式:
第1行,1个整数,表示最小的总代价。
第2行,若干个整数,用空格分隔,表示总代价最小时每次切割的代价。
输入样例:
在这里给出一组输入。例如:
5
5 6 7 2 4
输出样例:
在这里给出相应的输出。例如:
54
24 13 11 6
作者
谷方明
单位
吉林大学
代码长度限制
16 KB
时间限制
100 ms
内存限制
5 MB
#include<bits/stdc++.h>
using namespace std;
long long sum;
priority_queue<long long,vector<long long>,greater<long long >>q;
vector<long long>s;
int main(){
long long x;
int n,i;
long long m,z;
cin>>n;
if (n == 1)
{
cout<<'0';
return 0;
}
for(i=0;i<n;i++){
cin>>x;
q.push(x);
}
for(i=1;i<=n-1;i++){
m=q.top();
q.pop();
z=q.top();
q.pop();
q.push(m+z);
sum+=(m+z);
s.push_back(m+z);
}
cout<<sum<<endl;
for(i=n-2;i>=1;i--)
cout<<s[i]<<" ";
cout<<s[0];
}
我的思路:
这道题如果知道priority_queue的话是很简单的,但是千万不要用multiset来做,不然会内存超限!!在构建优先队列的时候,注意要构建一个小根堆,每次取最小的两个,然后将它们出队,再将他们的和入队,用一个数组去存储它们的和,最后再将它们按倒序输出。
7-4 序列乘积 (100 分)
两个递增序列A和B,长度都是n。令 Ai 和 Bj 做乘积,1≤i,j≤n.请输出n*n个乘积中从小到大的前n个。
输入格式:
第1行,1个整数n,表示序列的长度, 1≤n≤100000.
第2行,n个整数Ai,用空格分隔,表示序列A,1≤Ai≤40000,1≤i≤n.
第3行,n个整数Bi,用空格分隔,表示序列B,1≤Bi≤40000,1≤i≤n.
输出格式:
1行,n个整数,用空格分隔,表示序列乘积中的从小到大前n个。
输入样例:
在这里给出一组输入。例如:
5
1 3 5 7 9
2 4 6 8 10
输出样例:
在这里给出相应的输出。例如:
2 4 6 6 8
作者
谷方明
单位
吉林大学
代码长度限制
16 KB
时间限制
100 ms
内存限制
5 MB
#include<bits/stdc++.h>
using namespace std;
priority_queue<long long>q;
long long a[100000],b[100000],c[100000];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
long long i,j,n,m=0;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<n;i++)
cin>>b[i];
for(i=0;i<n;i++)
q.push(a[0]*b[i]);
for(i=1;i<n;++i)
for(j=0;j<n;++j){
if(a[i]*b[j]>q.top()) break;
else{
q.push(a[i]*b[j]);
q.pop();
}
}
while(!q.empty()){
c[m++]=q.top();
q.pop();
}
for(i=m-1;i>=1;i--)
cout<<c[i]<<" ";
cout<<c[0];
}
我的思路:
这道题目是去用堆优化的,而STL中的priority_queue的本质就是一个堆,在默认情况下它就是一个大根堆。首先我们将a[0]*b[i]存入堆中,然后做循环,每次取堆顶元素和a[i]*a[j]来比较,如果后者大的话,就直接break,否则就将其压入优先队列。最后以倒序的方式打印队列即可。