Wool
Accepts: 109
Submissions: 770
Time Limit: 8000/4000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
黎明时,Venus为Psyche定下了第二个任务。她要渡过河,收集对岸绵羊身上的金羊毛。 那些绵羊狂野不驯,所以Psyche一直往地上丢树枝来把它们吓走。地上现在有n根树枝,第i根树枝的长度是ai. 如果她丢的下一根树枝可以和某两根树枝形成三角形,绵羊就会被激怒而袭击她。 现在Psyche手中只有长度不小于L且不大于R的树枝。请你帮忙计算,她下一根可以丢多少种不同长度的树枝而不会把绵羊激怒呢?
输入描述
第一行,一个整数T(1≤T≤10),代表数据组数。 对于每组数据,第一行有三个整数n,L,R (2≤n≤105,1≤L≤R≤1018)。 第二行,n个整数,第i个整数为ai (1≤ai≤1018),代表第i根树枝的长度。
输出描述
输出T行,对于每组数据,输出选取方式总数。
输入样例
2 2 1 3 1 1 4 3 10 1 1 2 4
输出样例
2 5
Hint
对于第一组数据,可以选用长度为2,3的树枝。 对于第二组数据,可以选用长度为6,7,8,9,10的树枝。
解题思路:
考虑三角形的判断条件,a + b > c && a - b < c(a >= b)
那么只需要把未知的那个边当作c这条边,已知的当作a,b两条边
然后求在[l, r]区间内,不属于(a-b, a+b)的区间里的整数即可
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL > pi;
const int maxn = 1e5;
pi b[maxn];
LL a[maxn];
bool cmp(pi x, pi y){
return (x.first == y.first ? (x.second > y.second) : (x.first < y.first));
}
int main()
{
// freopen("test.in", "r+", stdin);
// freopen("test.out", "w+", stdout);
LL t, n, L, R;
scanf("%lld", &t);
while(t--){
scanf("%lld%lld%lld", &n, &L, &R);
for(int i = 0; i < n; ++i) scanf("%lld", &a[i]);
sort(a, a + n);
for(int i = 0; i < n - 1; ++i){
b[i].first = a[i+1] - a[i];
b[i].second = a[i+1] + a[i];
}
if(n - 1 >= 2)
sort(b, b + n - 1, cmp);
LL ans = 0, tmp1 = L, tmp2 = L;
for(int i = 0; i < n - 1; ++i){
if(b[i].second <= L) continue;
if(b[i].first > R) break;
if(b[i].first >= tmp2){
tmp1 = b[i].first;
ans += tmp1 - tmp2 + 1;
}
if(b[i].second > tmp2){
tmp2 = b[i].second;
}
if(tmp2 > R){
tmp2 = R + 1;
break;
}
}
ans += (R >= tmp2 ? (R - tmp2 + 1) : 0 );
printf("%lld\n", ans);
}
return 0;
}