链接:https://www.nowcoder.com/questionTerminal/9363dcb83ca44c61a2c1a8f65aa722b8
来源:牛客网

金闪闪死后,红A拿到了王之财宝,里面有n个武器,长度各不相同。红A发现,拿其中三件武器首尾相接,组成一个三角形,进行召唤仪式,就可以召唤出一个山寨金闪闪。(例如,三件武器长度为101520,可以召唤成功。若长度为101130,首尾相接无法组成三角形,召唤失败。)红A于是开了一个金闪闪专卖店。他把王之财宝排成一排,每个客人会随机抽取到一个区间[l,r],客人可以选取区间里的三件武器进行召唤(客人都很聪慧,如果能找出来合适的武器,一定不会放过)。召唤结束后,客人要把武器原样放回去。m个客人光顾以后,红A害怕过多的金闪闪愉悦太多男人,于是找到了你,希望你帮他统计出有多少山寨金闪闪被召唤出来。

 

输入描述:
第一行武器数量:n <= 1*10^7
第二行空格分隔的n个int,表示每件武器的长度。
第三行顾客数量:m <= 1*10^6
后面m行,每行两个int l,r,表示每个客人被分配到的区间。(l<r)


输出描述:
山寨金闪闪数量。
示例1

输入

5
1 10 100 95 101
4
1 3
2 4
2 5
3 5

输出

3
题解思路:
1,首先,判断三个正整数a,b,c是否能组成三角形,判断方法是:将abc排序(a<=b<=c),然后如果a+b>c,则可以构成三角形。
2,其次,判断一个区间[L,R]内是否能找到三个数使其构成三角形,可以将这R-L+1个元素取出并排序,然后从前往后三个三个判断,复杂度是O(len*log(len))。
3,查询每次区间长度都在1~1e7之间,当然不能每次都暴力找,不然有1e6次查询,时间复杂度肯定爆炸,那么怎么处理呢?
4,实际上,如果数一多,是非常容易构成三角形的,如果要刚好卡到边界,刚好不能构造成三角形(a+b==c),则要构造这样的数据:1,1,2,3,5,8......。
对,其实就是斐波那契数列,题目的数据给出的数据在int范围内,然后我们发现大概在40多项的时候就不能构造出全都不满足构成三角形的数据了,下面是打表的出的结果。
所以,只要在给出的区间长度较大的,一定能构成三角形,区间长度较小的,则可以存下来排序后判断,所以本题最后的时间复杂度是O(m*45*log(45))。
本题在今年杭电多校中还出现更难版本,题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6601
#include<bits/stdc++.h>
using namespace std;
const int MAXN=(int)1e7 + 5;
int n,a[MAXN],m;
vector<int>v;
int main() {
    while(~scanf("%d",&n)) {
        for(int i=1; i<=n; i++)scanf("%d",&a[i]);
        scanf("%d",&m);
        int cnt=0;
        while(m--) {
            int l,r;
            scanf("%d%d",&l,&r);
            if(r-l+1>=47)cnt++;
            else if(r-l+1<3)continue;
            else {
                v.clear();
                for(int i=l; i<=r; i++)v.push_back(a[i]);
                sort(v.begin(),v.end());
                int len=v.size();
                bool flag=0;
                for(int i=0; i<len-2; i++) {
                    if(v[i]+v[i+1]>v[i+2]) {
                        flag=1;
                        break;
                    }
                }
                if(flag)cnt++;
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}