三角合击题解【C++】

题目描述

兔子军团凭借着独有的三角合击技能,成为了地表最强的军团。
免子军团共有 N 名士兵,每位士兵都有一把刃长为 Li 的佩剑,如果三位士兵的佩剑刃长能组成一个三角形,则说明其属性相符,则这三位士兵可以合力使出一次三角合击,击退敌军。
兔子军团的司令小喵正在检阅这支军团,他想知道,如果任意的三位士兵只能组合一次,军团能使出多少次三角合击?

输入格式

共两行:
第一行一个整数 N ,表示军团的士兵数量;
第二行 N 个整数瓜,依次表示第 i 位士兵佩剑的刃长。

输出格式

一行一个整数,输出三角合击的次数。

样例输入1

3
4 2 3

样例输出1

1

样例1解析

第 1,2,3 位士兵的佩剑组成边长为 {4,2,3} 的三角形,能使出 1 次三角合击。

样例输入2

7
218 786 704 233 645 728 389

样例输出2

23

数据范围

对于 40% 的数据: 3 ≤ N ≤ 100 ; 1 ≤  ≤  ; 
对于 100% 的数据: 3 ≤ N ≤ 2 x  ;  1 ≤  ≤  

解法分析

枚举 + 二分查找:

朴素做法的时间复杂度为 \small O(N^{3}),观察数据范围显然不能通过。

根据三角形的形成规则来优化求解过程,枚举三角形的两边 \small x 和 \small y ,显然第三边 \small z 的取值范围为\small [\left | x-y \right |, x+y ] 。二分找到区间的左端点 \small l 和右端点 \small r,特判一下小于 \small x,y 的情况,然后将贡献计入答案中。

输出时需注意除以 3 去掉重复方案,时间复杂度优化至 \small O(N^{2}\log_{N})

参考代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n, a, x, y, len,ans;
vector<int> l;
int main() {
    cin >> n;
    for(int i = 0; i < n; i++){
    cin >> a;
    l.push_back(a);
    }
    sort(l.begin(), l.end());
    for(int i = 0; i < n;i++){
        for(int j = i + 1; j < n; j++){
            x = l[i], y = l[j];
            auto st = upper_bound(l.begin(), l.end(), abs(x - y));
            auto ed = lower_bound(l.begin(), l.end(), (x + y));
            len = ed - st;
            if(abs(x - y) < x) len--;
            if(abs(x - y) < y) len--;
            if(len > 0) ans += len;
        }
    }
    ans /= 3;
    cout << ans << endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值