牛客小白月赛4——A 三角形

链接:https://ac.nowcoder.com/acm/contest/134/A
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

铁子从森林里收集了n根木棍,她开始将它们按顺序的排成一排,从左到右依次为1到n,她回想起
在数学课上老师教她的三角形知识,她开始从这些木棍中间找三根木棍来组成一个周长最大的三角形,
这时她的兄弟顺溜偷偷的溜了过来,偷走了第i根木棍,现在她想知道现在能够组成周长最大的三角形
的周长是多少?

输入描述:

第一行两个整数n和q。(1 ≤ n, q ≤ 10^5)
第二行n个整数表示第i根木棍的长度ai。(1 ≤ ai ≤ 10^9)
接下来q行,每行一个整数表示被顺溜偷走的木棍编号。注意每行的事件是独立的,也就是说每一次操作都是对于原来的n根木棍进行的。

 

输出描述:

对于每个询问输出一行表示答案,如果删除木棍后无法组成三角形则输出 -1 。

示例1

输入

6 2
1 2 3 4 5 6
6
5

输出

12
13

解题思路:

        构成三角形的原则是任意两边之和大于第三边,且题目要求求周长最大的三角形,那么木棍按长度排序后,选取最长的三个木棍判断是否构成三角形。如果不构成三角形,更换第二长的或第三长的也无法构成三角形(因为第二长和第三长的木棍已经是剩下木棍中长度和最大的),所以此时舍弃最长的木棍向后查找直到找到即可,时间复杂度O(n)。

        int最大值为2147483647,而木棍长度最大值为10^9,3根木棍的长度和可能大于int最大值,所以最后结果需要用long long存储。

AC代码:

#include <iostream>
#include <algorithm>
 
using namespace std;
//排序会打乱下标,而题目对于每个询问需要排除指定下标的木棍,所以用结构体记录原下标
struct Elem {
    int index, length;
};

bool cmp(Elem a, Elem b){
    return a.length > b.length;
}

int main(){
    int n, q;
    Elem a[100001] = {};
    cin >> n >> q;
    for(int i = 0; i < n; i++){
        //index + 1与题目输入对应
        a[i].index = i + 1;
        cin >> a[i].length;
    }
    //对长度进行降序排序
    sort(a, a + n, cmp);
    while(q--){
        int t;
        cin >> t;
        //默认选取最大的3个(记录下标)
        int choose_index[3] = {0, 1, 2};
        do{
            if(choose_index[2] >= n){
                break;
            }  
            //如果不能构成三角形
            if(a[choose_index[2]].length + a[choose_index[1]].length <= a[choose_index[0]].length){
                //舍弃最大的
                choose_index[0]++;
                //重复的下标后移
                for(int i = 1; i < 3; i++){
                    if(choose_index[i] == choose_index[i - 1]){
                        choose_index[i]++;
                    }
                }
            }
            if(choose_index[2] >= n){
                break;
            }
            //判断是否有被舍弃的木棍
            for(int i = 0; i < 3; i++){
                if(a[choose_index[i]].index == t){
                    choose_index[i]++;
                }
            }
            for(int i = 1; i < 3; i++){
                if(choose_index[i] == choose_index[i - 1]){
                    choose_index[i]++;
                }
            }
            //如果较短的两边之和小于第三边,则继续选择
        }while(choose_index[2] < n && a[choose_index[2]].length + a[choose_index[1]].length <= a[choose_index[0]].length);
        //如果越界说明找完了也没有符合条件的木棍
        if(choose_index[2] >= n){
            cout << -1 << endl;
        } else {
            long long sum = 0;
            for(int i = 0; i < 3; i++){
                sum += a[choose_index[i]].length;
            }
            cout << sum << endl;
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值