码迷,mamicode.com
首页 > 其他好文 > 详细

【Codeforces Round #643 (Div. 2) C】Count Triangles

时间:2020-12-10 11:30:51      阅读:9      评论:0      收藏:0      [点我收藏+]

标签:strong   题解   space   链接   main   ref   http   name   比较   

题目链接

链接

翻译

让你找 \(3\) 条边 \(x,y,z\), 要求 \(A\le x\le B\le y\le C\le z\le D\)

\(x,y,z\) 能组成三角形。

问你这样的 \(x,y,z\) 的个数。

题解

对于最后选出来的边,我们只需要关注 \(x+y\) 是不是大于 \(z\) 就好了 (两边之和大于第三边)。

因为 \(x<=y<=z\)\(x,y,z\) 都是正整数。所以 \(y+z>x\)\(z+x>y\) 恒成立。

首先, 比较明显的是我们可以先枚举其中一条边 \(x\)

然后 \(y\) 的话会从 \(B\)\(C\) 变化,那么 \(x+y\) 就会在 \([x+B,x+C]\) 这个区间内变化。

这个区间和 \([C,D]\) 这个区间的相交情况有 \(5\) 种可能(除去完全在 \([C,D]\) 左边这种情况不可能)。

分别把这 \(5\) 种情况画出来, 算一下 \(y\) 在这个区域里面对答案的贡献就好了(\(z\) 的值要比 \(x+y\) 来的小)。

会对应很多的类似1,2,3,4... 的公差为 \(1\) 的等差数列(用求和公式算一下答案)。以及整个 \([C,D]\) 区域的值都可以取的情况(x+y>D)。

强烈建议画个数轴来讨论!

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;

LL a,b,c,d;

int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> a >> b >> c >> d;
    LL ans = 0;
    for (LL x = a;x <= b;x++){
        if (x+b>d){
            ans += (d-c+1)*(c-b+1);
            continue;
        }
        if (x+b <= c && x+c <= d){
            ans += (1+x)*x/2;
        }
        if (x+b <= c && x+c > d){
            ans += (1+d-c)*(d-c)/2+(x+c-d)*(d-c+1);
        }
        if (x+b > c && x+c <= d){
            LL a1 = x+b-c,n = c-b+1;
            LL an = a1 + n - 1;
            ans += (a1+an)*n/2;
        }
        if (x+b > c && x+c > d){
            LL a1 = x + b - c;
            LL n = (d-x-b+1);
            LL an = a1 + n-1;
            ans += (a1+an)*n/2;
            ans += (x+c-d)*(d-c+1);
        }
    }
    cout << ans << endl;
    return 0;
}

【Codeforces Round #643 (Div. 2) C】Count Triangles

标签:strong   题解   space   链接   main   ref   http   name   比较   

原文地址:https://www.cnblogs.com/AWCXV/p/14093130.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!