區間加(差分數組)

區間加

鏈接:https://ac.nowcoder.com/acm/contest/4911/C

思路

分析每個元素與目標值mm之間的差值,可知相鄰的兩個元素之間差值不超過1,我們想到用差分數組求解本題;
首先用數組res[i]res[i] (res[i])=mres[i](res[i])=m-res[i]記錄第ii個元素與目標值之間的的差值,然後對相鄰數組resres作差分,記爲數組b[i]b[i](b[i])=res[i+1]res[i](b[i]) = res[i+1]-res[i];
爲了理解方便,我們將本題轉化爲左右括號放置問題,包含元素ii的左右括號對數(即該元素左邊左括號與右括號數目的差值)代表元素ii加1的次數,假設nownow爲當前未被匹配的左括號數目,f[i]f[i]爲第ii個元素的方案數,有以下3種情況:
(1)(1)(b[i])=1(b[i]) = 1,則第i+1i+1個元素比第ii個元素大1,則第ii個元素要多加一次,所以在其左邊的左括號數目加1即未匹配的左括號數now++now++
(2)(2)(b[i])=1(b[i]) = -1,則第i+1i+1個元素比第ii個元素小1,則第ii個位置放一個右括號,與此同時未匹配的左括號數減1,f[i]=f[i1]nowf[i]=f[i-1]*now--
(3)(3)(b[i])=0(b[i]) = 0,說明第i+1i+1個元素與第ii個元素相等,此時有兩種方案,一種是什麼都不做,另外一種是第ii個位置放上左右括號,因此f[i]=f[i1](now+1)f[i]=f[i-1]*(now+1)

代碼

#include <iostream>
#include <cmath>
using namespace std;
#define MAX 2010
#define mo 998244355
int res[MAX], b[MAX];
int n, m;
int main(){
	cin>>n>>m;
	for(int i = 1; i <= n; i++){
		cin>>res[i];
		res[i] = m - res[i];
	}
	for(int i = 0; i <= n; i++) b[i] = res[i+1] - res[i];
	int now = 0;
	long long ans = 1;
	for(int i = 0; i < n; i++){
		if(abs(b[i]) > 1){
			cout<<"0"<<endl;
			return 0;
		}
		if(b[i] == 0) ans = ans * (now + 1) % mo; 
		if(b[i] == 1) now++;
		if(b[i] == -1) ans = ans * now-- % mo;
	}
	cout<<ans<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章