Codeforces Round #643 (Div. 2) C. Count Triangles-- 差分、前綴和

題意

給你 A,B,C,DA , B , C , D
問有多少種方法構造出三角形(X,Y,Z)(X , Y , Z)使得 1AXBYCZD<=1051≤A ≤ X ≤ B ≤ Y ≤ C ≤ Z ≤ D <= 10^5

思路

組成三角形的條件是2邊之和大於第三邊,這裏因爲XYZX≤Y≤Z
所以只需要x+y>zx+y>z,所以我們只要知道了x+yx+y的值之後,可以求出zz的可行範圍,但分別枚舉xyx,y肯定會超時,我們換個思路,直接枚舉x+yx+y或者說能得到x+y=px+y=px,yx,y有多少對,顯然當x=1ByCx=1時,B ≤ y ≤ C,所以組成的x+yx+y的值在[1+B,1+C][1+B ,1+C]區間,當x=2ByCx=2時,B ≤ y ≤ C,所以組成的x+yx+y的值在[2+B,2+C][2+B ,2+C]區間,顯然這些區間重疊到一起之後,對於某個點p的取值就是構成x+y=px,yx+y=p的x,y組合個數,然後這部分區間可以通過差分、前綴和求得S[]S[],此時得到的S[i]S[i]表示構成x+y=ix+y=i的組合對數。然後我們枚舉zz,對應當前zx+y>zz,x+y>z,所以答案就是S[z+1]+S[z+2]+.....+S[maxn1]S[z+1] + S[z+2] + ..... + S[maxn-1] 然後這部分的區間值我們同樣可以用前綴和來維護,最後S[maxn1]S[z]S[maxn-1] - S[z]就是答案。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 1e6+10;
#define IOS ios::sync_with_stdio(0)
typedef long long ll;
const ll mod = 1e9+7;
ll sum[man];

int main() {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    int a,b,c,d;
    cin >>a >> b >>c >> d;
    for(int i = a;i <= b;i++)sum[i+b]++,sum[i+c+1]--;//區間修改
    for(int i = 1;i < man;i++)sum[i]+=sum[i-1];//所有區間加1,重疊地方累加
    for(int i = 1;i < man;i++)sum[i]+=sum[i-1];//對x+y的數量求一個前綴和,O(1)得到答案
    ll ans = 0;
    for(int i = c;i <= d;i++){
        ans += sum[man-1] - sum[i];
    }    
    cout << ans << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章