CF1355C Count Triangles

传送门

 

 

 

思路:我们需要满足 x + y > z  ,  x + z > y ,  y + z > x .因为 A <= X <=B <= Y <= C <= Z <= D,所以 X + Z > Y和 Y + Z > X明显一定满足,所以我们只需要确定X + Y > Z的个数了.X∈[A,B],Y∈[B,C],则我们发现若X = A,则 X + Y = [A + B, A + C], X = A + 1, X + Y = [A + B + 1, A + C + 1].可以看出这就是区间+1操作,这样我们只需要枚举X的取值范围得到一个[L,R],让该区间值+1,最后我们就可以得到X+Y=[A+B,B+C]中任意一个数值的方案数,然后得到一个前缀和数组P[i],表示X+Y=[1,i]的总方案数.这样我们只需要枚举Z∈[C,D],对于每个Z的答案就是P[B+C] - P[Z],当然如果当前的Z>=B+C需要考虑。而上面的区间+1操作可以用差分来解决,或者线段树也可以。复杂度就是O(N)。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 #include <vector>
 8 #include <cstring>
 9 #include <functional>
10 #include <map>
11 #define LL long long
12 #define lson(rt) (rt << 1)
13 #define rson(rt) (rt << 1 | 1)
14 using namespace std;
15 
16 const int N = 1e6 + 10;
17 long long x[N], y[N];
18 
19 void solve ()
20 {
21     int a, b, c, d;
22     scanf("%d%d%d%d", &a, &b, &c, &d);
23     for(int i = a; i <= b; ++i) {
24         x[i + b] += 1;
25         x[i + c + 1] -= 1;
26     }
27     int n = b + c;
28     for(int i = 1; i <= n; ++i) x[i] += x[i - 1];
29     for(int i = 1; i <= n; ++i) y[i] += y[i - 1] + x[i];/*
30     for(int i = 1; i <= s; ++i) cout << x[i] << " ";
31     cout << endl;
32     for(int i = 1; i <= s; ++i) cout << y[i] << " ";
33     cout << endl;*/
34     long long tot = 0;
35     for(int i = c; i <= d; ++i) {
36         if(i >= b + c) break;
37         tot += (LL)y[b + c] - y[i];
38     }
39     //cout << "tot = " << tot << endl;
40     printf("%lld\n", tot);
41 }
42 
43 int main ()
44 {
45     solve();
46 
47     return 0;
48 }

 

posted @ 2021-01-16 01:16  SummerMingQAQ  阅读(158)  评论(0编辑  收藏  举报