有人说这套题C比D和E 从过题的人数上来看确实这样 D题很好想 过的人很多 E题大佬说是三分裸题(大佬总能一眼看出)等下就补E
我们来讲讲C题 其实有个很简单的而且细节也很少的方法 当时想了想 被队友叫去搞D了
主要就是利用前缀和思想(虽然我求的是后缀)
我们知道 在 X<=Y<=Z的情况下 要构成三角形就只有一个限制 那就是 X+Y>Z
我们肯定要从a,b,c,d这几个范围下手
先枚举最小的那条边
a<=X<=b 从a到b枚举一遍
对于第2条边 我们通过它界定一个范围 我们知道第二条边的最大值是 b 最小值是c
那么 我们得到一个初步的范围 X+b-1,X+c-1
这是第三条边的一个可行边界范围(我乱说的 不知道怎么说)
大概意思是 对于 X和c 这两条边来说 最大的可行边就是 X+c-1
对于 X和c-1 这两条边来说 最大的可行边就是 X+c-2
...以此类推 对于 X和b 这两条边来说 最大的可行边就是 X+b-1
那么我们进行后缀和的修改
对于 后缀和数组q
q[x+b-2]--,q[x+c-1]++;
X+b-2 X+b-1 X+b X+b+1...... X+c-2 X+c-1
-1 0 0 0 0 1
这样 我们做一遍后缀和
X+b-2 X+b-1 X+b X+b+1...... X+c-2 X+c-1
0 1 1 1 1 1
但是这仅仅是把每一种组合的边界标记出来 并没有得到完整的可行边(比如比边界边小一些的)
我们考虑一下 对于 边界是 X+c-1 的组合 是不是所有 c<=k<=X+c-1 的边都是可行解
也就是说任何小于边界边的边都是可以计入答案的
那么对于上面的后缀和 只标记出了边界边 我们再做一次后缀和 就可以完美的标记出每条边作为最大边对答案的贡献了
X+b-2 X+b-1 X+b X+b+1...... X+c-2 X+c-1
c-b+1 c-b+1 c-b c-b-1 2 1
最后我们只要计算区间 c~d之间的和就行啦
为了方便 我把数组开大了一倍
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
ll q[N];
int main(){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int i = a; i <= b; i++){
int l = i+b-1;
int r = i+c-1;
q[l-1]--;
q[r]++;
}
for(int i = N-2; i >= 1; i--) q[i]+=q[i+1];
for(int i = N-2; i >= 1; i--) q[i]+=q[i+1];
ll ans = 0;
for(int i = c; i <= d; i++) ans+=q[i];
printf("%lld\n",ans);
return 0;
}