问题描述
黎明时, Venus 为 Psyche 定下了第二个任务。她要渡过河,收集对岸绵羊身上的金羊毛。
那些绵羊狂野不驯,所以
Psyche
一直往地上丢树枝来把它们吓走。地上现在有
n
根树枝,第
如果她丢的下一根树枝可以和某两根树枝形成三角形,绵羊就会被激怒而袭击她。
现在Psyche手中只有长度不小于
L
且不大于
输入描述
第一行,一个整数 T(1≤T≤10) ,代表数据组数。
对于每组数据,第一行有三个整数 n,L,R (2≤n≤10 5 ,1≤L≤R≤10 18 ) .
第二行,
n
个整数,第
输出描述
输出
输入样例
2
1
4
1
输出样例
2
Hint
对于第一组数据,可以选用长度为
2,3
的树枝。
对于第二组数据,可以选用长度为
6,7,8,9,10
的树枝。
Solution
这一题只需要考虑地板上的树枝与扔下去的树枝构成三角形。
对于地板上的两根树枝,长度为
a,b
(a>b)
,它们会让
(a−b,a+b)
这个区间长度内的树枝无法扔下。
那么考虑对于一根长度为
a i
的树枝,对所有的
a j ≤a k ≤a i
,会有
(a i −a j ,a i +a j )⊆(a i −a k ,a i +a k )
我们考虑记录每根树枝为主,它与比其小的树枝能构成三角形的区域。这样我们就有了
2n
个事件点,每个事件点的含义是从这个点开始,后面一段区间被覆盖了,或者是从某个区间的影响范围到这个点为止。
至于如何求出事件点……对
a
排序,与
扫到左端点,区间值加
1
,右端点减
坑点:
1、各种边界(博主原本有些变量没开longlong,在奇怪的地方炸了)
(2、比赛时标程写错了……)
#include<stdio.h>
#include<algorithm>
#define M 200005
typedef long long ll;
struct seg{ll c,p;}b[M];
ll l,r,ans,a[M],p,now,n,t;
inline bool cmp(const seg &a,const seg &b){return a.c<b.c;}
int main()
{
scanf("%I64d",&t);
while (t--)
{
scanf("%I64d%I64d%I64d",&n,&l,&r);
ans=now=p=0;
for (int i=1;i<=n;i++) scanf("%I64d",a+i);
std::sort(a+1,a+n+1);
for (int i=1;i<n;i++)
{
b[i].c=a[i+1]-a[i]+1,b[i].p=1;
b[i+n-1].c=a[i+1]+a[i],b[i+n-1].p=-1;
}
int m=(n-1)<<1;
std::sort(b+1,b+m+1,cmp);
for (int i=1;b[i].c<l;i++) now+=b[p=i].p;
b[p++].c=l;
for (;p<=m && b[p].c<=r;)
{
if (now<=0) ans+=b[p].c-b[p-1].c;
now+=b[p++].p;
while (b[p].c==b[p-1].c) now+=b[p++].p;
}
if (now<=0) ans+=r-b[p-1].c+1;
printf("%I64d\n",ans);
}
}