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 ", ans); } return 0; }