山寨金闪闪

题目描述

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

输入描述

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

解题思路

  三个数中,较小的那两个的和大于第三个就一定可以构成三角形,因此,对于[l,r]区间的数来说,只要找到这样的三个数就可以,为了减少运算,可以将其排序,然后从前到后每三个为一组进行比较,比如x1,x2,x3,x4,x1,x2,x3无法构成之后,可以直接进行x2,x3,x4的比较,x1不需要再参与计算中。这样的事件复杂度为O(NlongN),由于N可以达到10^7,所以直接暴力搜索一定会超时。
  因为数据越多越容易构成三角形,边界情况就是两边之和等于第三边,a+b=c,那么如果去构造这样一个刚好找不到三角形的序列,则是1,1,2,3,5,,,Fibonacci数列,这个数列在int的表示范围内大概到46项,那么也就是说,当数量超过46的时候一定可以构成三角形(超过46一定会存在一个数字x,不属于Fibonacci数,可以插在满足fi-1<x<fi,因为fi-1+fi-2=fi,那么fi-1+fi-2>x,所以一定存在三角形)。
  这样之需要对数量小于46的序列进行查找就可以了,大大减少了数据量。

实现代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
	int n,m,i;
	cin>>n;
	vector<int> data(n+1,0);
	for(i=1;i<=n;i++)
		cin>>data[i];
	cin>>m;
	int l,r,cnt=0;
	for(i=0;i<m;i++){
		cin>>l>>r;
		if(r-l<2)
			continue;
		else if(r-l>=46)
			cnt++;
		else{
			vector<int> v;
			for(int j=l;j<=r;j++)
				v.push_back(data[j]);
			sort(v.begin(),v.end());
			for(int j=0;j<v.size()-2;j++)
				if(v[j]+v[j+1]>v[j+2]){
					cnt++;
					break;
				}
		}
	}
	cout<<cnt<<endl;
	return 0;	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值