P9461 「EZEC-14」众数 II

P9461 「EZEC-14」众数 II

题意

略。

思路

发现如果区间包含的 \(a_i\) 都是完整的,那么最小众数一定是 \(1\)。

否则如果 \(a_l\) 只有一段后缀 \([x,a_l]\) 和 \(a_r\) 只有一段前缀 \([1,y]\),当且仅当 \(\forall i \in [l,r], a_i \ge x\) 时最小众数是 \(x\),否则还是 \(1\)。

没有其他情况。


为了方便,我们转为求出所有最小众数为 \(x(x>1)\) 的子区间,贡献 \(x-1\)。

然后所有子区间再贡献一个 \(1\)。这部分显然是好求的。


\(\forall i \in [l,r], a_i \ge x\) 这个条件,让我们想到小根笛卡尔树。

对于笛卡尔树上一个节点 \(u\),在它的左子树取一个 \(l\),右子树取一个 \(r\),计算贡献。显然这样的子区间最小众数为 \(x \in [1,a_u]\)。

这里最小众数为 \(x\) 的时候有几个子区间?

左端点可以取左子树上任意一个点或者点 \(u\) 的高度 \(x\) 的位置,有 \(siz_{ls} +1\) 种方案。

右端点可以取右子树上任意一个点或者点 \(u\) 的高度 \(\ge x\) 的位置,有 \((sum_{rs}+a_u) - (x-1)(siz_{rs}+1)\) 种方案。

每个方案的贡献是 \(x-1\)。

所以 \(u\) 的子树的总贡献是:

\[\sum_{x=1}^{a_u} (x-1) (siz_{ls}+1) ((sum_{rs}+a_u)-(x-1)(siz_{rs}+1)) \]

化简一下,变成:

\[\begin{aligned} & (siz_{ls}+1) \sum_{x=1}^{a_u} (sum_{rs}+a_u) (x-1) -(siz_{rs}+1)(x-1)^2 \\ = & (siz_{ls}+1) ((sum_{rs}+a_u) (\sum_{x=1}^{a_u-1} x) - (siz_{rs}+1) (\sum_{x=1}^{a_u-1} x^2)) \\ = & (siz_{ls}+1) ((sum_{rs}+a_u)\frac{a_u(a_u-1)}2 - (siz_{rs}+1) \frac{(a_u-1)a_u(2a_u-1)}{6}) \end{aligned} \]

是不是做完了。

可以线性做,但是单 \(\log\) 可以少写点东西。

code

cpp 复制代码
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {
	constexpr int N=1e6+7,mod=998244353,V=1e6;
	struct modint {
		int x;
		modint (int y=0) : x(y) {} 
		modint operator + (modint b) const { return x+b.x<mod ? x+b.x : x+b.x-mod; }
		modint operator - (modint b) const { return x-b.x<0 ? x-b.x+mod : x-b.x; }
		modint operator * (modint b) const { return 1ll*x*b.x%mod; }
		modint &operator += (modint b) { return *this = *this + b; }
		modint &operator *= (modint b) { return *this = *this * b; }
	};
	int n,a[N];
	int tr[N];
	void add(int x,int w) {
		for(;x<=V;x+=x&-x) tr[x]=max(tr[x],w);
	}
	int ask(int x) {
		int s=0;
		for(;x;x-=x&-x) s=max(s,tr[x]);
		return s;
	}
	modint b[N];
	int lt[N],rt[N];
	modint ans;
	void main() {
		sf("%d",&n);
		rep(i,1,n) sf("%d",&a[i]), b[i]=b[i-1]+a[i];
		rep(i,1,n) {
			lt[i]=ask(a[i])+1;
			add(a[i],i);
		}
		memset(tr,0,sizeof(tr));
		per(i,n,1) {
			rt[i]=n-ask(a[i]-1);
			add(a[i],n-i+1);
		}
		// rep(i,1,n) pf("%d %d\n",lt[i],rt[i]);
		rep(i,1,n) ans+=((b[rt[i]]-b[i-1])*(1ll*a[i]*(a[i]-1)/2%mod)-(modint)(rt[i]-i+1)*(1ll*(a[i]-1)*a[i]*(2*a[i]-1)/6%mod))*(i-lt[i]+1);
		ans+=b[n]+(1ll*b[n].x*(b[n].x-1)/2%mod);
		pf("%d\n",ans.x);
	}
}
int main() {
	#ifdef LOCAL
	freopen("in.txt","r",stdin);
	freopen("my.out","w",stdout);
	#endif
	wing_heart :: main();
}