LGP4229题解

某位寄吧的故事

下文的 \(m\) 即为题面中的 \(Q\)

离散化,把序列变成 \(O(2m)\) 个部分,然后对这 \(O(2m)\) 个部分把最大值求出来,每次把最大值相同的部分拉出来,再把限制和这个最大值相同的也拉出来。我们假装这个最值叫 \(c\)

然后是 \(dp\)\(dp[n][k]\) 表示推到第 \(n\) 段,上一个最大值在第 \(k\) 段时的合法方案数量。

注意到如果两个区间有包含关系,那么大的那个区间相当于不存在。

\(L[n]\) 表示右端点在第 \(n\) 段的区间中,左端点最靠右的那个左端点。如果没有那就是 \(0\)没说就是零卡

然后设 \((l[n],r[n]]\) 为第 \(n\) 段区间在原序列上的左右端点。

不难发现这题其实是 P5204 的加强版(雾)

\[dp[n][k]=[L[n]\leq k]dp[n-1][k]\times(c-1)^{r[n]-l[n]} \]

\[dp[n][n]=\sum_{i=1}^{n-1}dp[n-1][i]\times(c^{r[n]-l[n]}-(c-1)^{r[n]-l[n]}) \]

游戏结束。

复杂度 \(O(m\log n)\)

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
typedef unsigned ui;
const ui M=505,mod=998244353;
ui n,m,A,s,k[M],V[M],tl[M],tr[M],l[M<<1],r[M<<1];ui len,lsh[M<<1];
std::vector<ui>c[M],q[M];
inline ui max(const ui&a,const ui&b){
	return a>b?a:b;
}
inline ui min(const ui&a,const ui&b){
	return a>b?b:a;
}
inline ui pow(ui a,ui b){
	ui ans(1);for(;b;b>>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;return ans;
}
inline ui Solve(const ui&k){
	static ui L[M<<1],dp[M<<1],tag[M<<1];
	const ui&v=V[k],&len=c[k].size();
	for(ui i=0;i<len;++i)L[i]=0,tag[i]=1;
	for(ui&id:q[k]){
		const ui&l=std::lower_bound(c[k].begin(),c[k].end(),tl[id])-c[k].begin();
		const ui&r=std::upper_bound(c[k].begin(),c[k].end(),tr[id])-c[k].begin()-1;
		if(l<=r)L[r]=max(L[r],l);else return 0;
	}
	for(ui i=1;i<len;++i)L[i]=max(L[i],L[i-1]);
	ui id(0),sum(1),mul(1);dp[0]=1;
	for(ui i=1;i<len;++i){
		while(id<L[i-1])mul=1ull*mul*tag[id]%mod,sum=(sum+1ull*(mod-mul)*dp[id++])%mod;
		const ui&v1=pow(v-1,r[c[k][i]]-l[c[k][i]]),&v2=pow(v,r[c[k][i]]-l[c[k][i]]);
		tag[L[i-1]]=1ull*tag[L[i-1]]*v1%mod;tag[i]=1ull*tag[i]*pow(v1,mod-2)%mod;
		dp[i]=1ull*sum*(mod+v2-v1)%mod;sum=(1ull*sum*v1+dp[i])%mod;
	}
	while(id<L[len-1])mul=1ull*mul*tag[id]%mod,sum=(sum+1ull*(mod-mul)*dp[id++])%mod;
	return sum;
}
struct sgt{
	ui G,mx[M<<3];
	inline void init(const ui&n){
		for(G=1;G<=n+1;G<<=1);for(ui i=1;i<=n;++i)mx[G+i]=A;for(ui i=1;i<G;++i)mx[i]=0x7fffffff;
	}
	inline void Cover(ui l,ui r,const ui&V){
		for(l+=G-1,r+=G+1;l^r^1;l>>=1,r>>=1){
			if(~l&1)mx[l^1]=min(mx[l^1],V);
			if(r&1)mx[r^1]=min(mx[r^1],V);
		}
	}
	inline void pushdown(){
		for(ui u=1;u<G;++u)mx[u<<1]=min(mx[u<<1],mx[u]),mx[u<<1|1]=min(mx[u<<1|1],mx[u]);
	}
}SGT;
signed main(){
	ui T;scanf("%u",&T);
	while(T--){
		ui ans(1);
		scanf("%u%u%u",&n,&m,&A);len=0;lsh[++len]=0;lsh[++len]=n;
		for(ui i=1;i<=m;++i)scanf("%u%u%u",tl+i,tr+i,k+i),--tl[i],lsh[++len]=tl[i],lsh[++len]=tr[i];
		std::sort(lsh+1,lsh+len+1);len=std::unique(lsh+1,lsh+len+1)-lsh-1;s=len-1;
		for(ui i=1;i<=s;++i)l[i]=lsh[i],r[i]=lsh[i+1];SGT.init(s);
		for(ui i=1;i<=m;++i){
			tl[i]=std::lower_bound(lsh+1,lsh+len+1,tl[i])-lsh;
			tr[i]=std::lower_bound(lsh+1,lsh+len+1,tr[i])-lsh-1;
			SGT.Cover(tl[i],tr[i],k[i]);
		}
		SGT.pushdown();len=0;
		for(ui i=1;i<=m;++i)lsh[++len]=k[i];lsh[++len]=A;
		std::sort(lsh+1,lsh+len+1);len=std::unique(lsh+1,lsh+len+1)-lsh-1;V[len]=A;
		for(ui i=1;i<=len;++i)c[i].resize(1);
		for(ui i=1;i<=m;++i){
			const ui&id=std::lower_bound(lsh+1,lsh+len+1,k[i])-lsh;
			q[id].push_back(i);V[id]=k[i];
		}
		for(ui i=1;i<=s;++i)c[std::lower_bound(lsh+1,lsh+len+1,SGT.mx[SGT.G+i])-lsh].push_back(i);
		for(ui i=1;i<=len;++i)ans=1ull*ans*Solve(i)%mod,std::vector<ui>().swap(c[i]),std::vector<ui>().swap(q[i]);
		printf("%u\n",ans);
	}
}
posted @ 2022-03-10 08:57  Prean  阅读(26)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};