2021-05-22

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,否则就将其压入优先队列。最后以倒序的方式打印队列即可。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值