C. Count Triangles

题意:给定A,B,C,D四个数,

    AxByCzD

   让我们求出符合条件的三角形的个数

思路:可以通过枚举一条边,其余两条通过计算来获得

     具体做法为:枚举一条边,然后将第二条边先定为最大值(即C),然后看看当前的情况能够拿(C,D)范围内的边来凑

         假如A B C D 分别为 3  6 9 11

         那么在第一次枚举的时候,我们先定第一、二条边为3,9  那么第三条边可以选取的范围为【9,11】即3个数,标记为sto

         这个时候我们再看看第二条边可以选取的范围【6,7,8,9】

         列举一下可知,当x==3时,有3 + 2 + 1=6种选取方式

         也就是说当第二条边的范围大于等于sto时,我们就有sto*(sto+1)/2种选法

         具体思路大致如此

         但是,有一些特殊情况

         (1)当枚举第一条边的数值大于第三条边的选取范围时,我们改一下上面的例子,改为 5 6 9 11

            那么当x==5时,有3+3+3种选取方式

         (2)当出现第二条边的选取范围小于sto时,计算方式改为  sto*(sto+1)/2-(base[limit])  //具体情况看代码

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=5e5+10;
 5 ll base[maxn];
 6 void init()
 7 {
 8     for(int i=1;i<=maxn-5;i++){
 9         base[i]+=base[i-1]+i;
10     }
11 }
12 int main()
13 {
14     init();
15     ll A,B,C,D;
16     scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
17     ll ans=0;
18     ll sto=0;
19     for(ll i=A;i<=B;i++){
20         ll tmpa=i; ll tmpb=D-C+1;
21         sto=tmpb;
22         if(tmpa<=tmpb){
23             //还需看看第二条边有多少种可能
24             ll limit=tmpa-(C-B+1);
25             if(limit<0) limit=0;
26             ans+=tmpa*(tmpa+1)/2;
27             ans-=base[limit];
28         }
29         else{
30             ll sum=tmpa-tmpb;
31             ll total=C-B+1;
32             if(sum>=(total-1)){
33                 ans+=total*sto;
34             }
35             else{
36                 ans+=sto*sum+sto*(sto+1)/2;
37                 ll limit=sto-total+sum;
38                 if(limit<0) limit=0;
39                 ans-=base[limit];
40             }
41         }
42     }
43     printf("%lld\n",ans);
44     return 0;
45 }

 

 

posted @ 2020-07-16 16:46  古比  阅读(214)  评论(0编辑  收藏  举报