CF Round #643 (Div. 2) C. Count Triangles

有人說這套題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;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章