区间加(差分数组)

区间加

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

思路

分析每个元素与目标值 m m m之间的差值,可知相邻的两个元素之间差值不超过1,我们想到用差分数组求解本题;
首先用数组 r e s [ i ] res[i] res[i] ( r e s [ i ] = m − r e s [ i ] ) (res[i]=m-res[i]) (res[i]=mres[i]记录第 i i i个元素与目标值之间的的差值,然后对相邻数组 r e s res res作差分,记为数组 b [ i ] b[i] b[i] ( b [ i ] = r e s [ i + 1 ] − r e s [ i ] ) (b[i]= res[i+1]-res[i]) (b[i]=res[i+1]res[i];
为了理解方便,我们将本题转化为左右括号放置问题,包含元素 i i i的左右括号对数(即该元素左边左括号与右括号数目的差值)代表元素 i i i加1的次数,假设 n o w now now为当前未被匹配的左括号数目, f [ i ] f[i] f[i]为第 i i i个元素的方案数,有以下3种情况:
( 1 ) (1) (1) b [ i ] = 1 b[i] = 1 b[i]=1,则第 i + 1 i+1 i+1个元素比第 i i i个元素大1,则第 i i i个元素要多加一次,所以在其左边的左括号数目加1即未匹配的左括号数 n o w + + now++ now++
( 2 ) (2) (2) b [ i ] = − 1 b[i] = -1 b[i]=1,则第 i + 1 i+1 i+1个元素比第 i i i个元素小1,则第 i i i个位置放一个右括号,与此同时未匹配的左括号数减1, f [ i ] = f [ i − 1 ] ∗ n o w − − f[i]=f[i-1]*now-- f[i]=f[i1]now
( 3 ) (3) (3) b [ i ] = 0 b[i] = 0 b[i]=0,说明第 i + 1 i+1 i+1个元素与第 i i i个元素相等,此时有两种方案,一种是什么都不做,另外一种是第 i i i个位置放上左右括号,因此 f [ i ] = f [ i − 1 ] ∗ ( n o w + 1 ) f[i]=f[i-1]*(now+1) f[i]=f[i1](now+1)

代码

#include 
#include 
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;
}

你可能感兴趣的:(牛客)