CF1591F Non-equal Neighbours

容斥,记 gig_i 表示 [1,i][1,i] 的答案。

gi=j=1i1gj×mink=j+1iak×(1)ij1g_i=\sum_{j=1}^{i-1}g_j\times \min_{k=j+1}^{i}a_k\times(-1)^{i-j-1}

fif_i 表示 gi×(1)ig_i\times(-1)^i,记 ssff 的前缀和。

然后单调栈维护点 ii 左边第一个小于等于它的数位置 kk,则转移方程为:fi=fkai×(si1sk1)f_i=f_k-a_i\times (s_{i-1}-s_{k-1})

时间复杂度 O(n)\mathcal O(n)

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define ha putchar(' ')
#define he putchar('\n')

inline int read()
{
	int x = 0;
	char c = getchar();
	while (c < '0' || c > '9')
		c = getchar();
	while (c >= '0' && c <= '9')
		x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x;
}

inline void write(int x)
{
	if(x > 9)
		write(x / 10);
	putchar(x % 10 + 48);
}

const int _ = 5e5 + 10, mod = 998244353;

int n, a[_], t, sk[_];

ll f[_], s[_];

signed main()
{
	n = read();
	for(int i = 1; i <= n; ++i) a[i] = read();
	f[1] = s[1] = -a[1], sk[++t] = 1;
	for(int i = 2; i <= n; ++i)
	{
		while(t && a[sk[t]] > a[i]) t--;
		if(t == 0) f[i] = -a[i] * (s[i - 1] + 1) % mod;
		else f[i] = (f[sk[t]] - a[i] * (s[i - 1] - s[sk[t] - 1])) % mod;
		s[i] = (s[i - 1] + f[i]) % mod;
		sk[++t] = i;
	}
	write(((n & 1 ? -1 : 1) * f[n] % mod + mod) % mod), he;
	return 0;
}
posted @ 2022-07-19 13:20  蒟蒻orz  阅读(1)  评论(0编辑  收藏  举报  来源