Justoj 2389: 拼接三角形 二分查找

 2389: 拼接三角形

时间限制: C/C++ 1 s      Java/Python 3 s      内存限制: 128 MB      答案正确: 7      提交: 21

提交 我的状态

题目描述

Ocean最爱三角形,现在Ocean手里有n条线段,Ocean现在想知道,这n条线段可以组成多少种三角形。

输入

一个整数nn(3≤n≤3000)(3≤n≤3000)

接下来nn个整数x(1≤x≤10000)x(1≤x≤10000)

输出

三角形的种类数

样例输入

6
3 2 4 2 5 2

样例输出

5

题解:通过cnt数组记录相同长度出现次数,容器v插入所有互不相同的数字,对v进行排序,然后开始遍历,找出比该数大的数组合成的三角形个数(前两个长度遍历,最后一个长度二分查找),对于出现过2次长度的特殊处理(等腰三角形),出现3次的数量加1(等边三角形)。

#include<iostream>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
vector<ll>v;
ll cnt[10011];
ll sort2(ll x,ll up){
        ll i=x,j=v.size()-1;
        while(i<=j){
                ll m=i+((j-i)>>1);
                if(v[m]>=up)
                        j=m-1;
                else
                        i=m+1;
        }
        return i-1;//i是第一个大于等于up的数字的下标
}
int main(){
        ll n,s;
        scanf("%lld",&n);
        while(n--){
                scanf("%lld",&s);
                if(!cnt[s])
                        v.push_back(s);
                cnt[s]++;
        }
        ll ans=0;
        sort(v.begin(),v.end());
        ll l=v.size();
        for(ll i=0;i<l;i++){
                if(cnt[v[i]]>=2){
                        for(ll j=0;v[j]<2*v[i]&&j<l;j++)
                                if(v[j]!=v[i])
                                        ans++;
                        if(cnt[v[i]]>=3)
                                ans++;
                }
                for(ll j=i+1;j<l-1;j++)
                        ans+=sort2(j+1,v[i]+v[j])-j;
        }
        printf("%lld\n",ans);
        return 0;
}

 

posted @ 2019-04-04 20:10  aeipyuan  阅读(173)  评论(0编辑  收藏  举报