P4229/P11288/AT_abc262_h 题解

题目链接:P4229 [清华集训 2017] 某位歌姬的故事P11288 [COTS 2017] 模板 Z1ABC262Ex - Max Limited Sequence

对值域 $ n $ 离散化,考虑每个位置被若干个区间覆盖然后有一个最小值,然后实际上只有两种状态,一种是取到顶,一种是不取,然后对区间排序一下就可以做 dp,$ dp[i][j] $ 表示考虑前 $ i $ 个区间上一个取到顶的位置在 $ j $,对于新的位置 $ k $ 可以将 $ i-1 $ 中所有合法的位置都转移过来然后乘至少有一个取到顶的方案数,其他位置乘不取到顶的方案数,然后就做完了。

代码(输入格式以 P4229 为准):

#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
const int mod=998244353;
struct dsu{
	vector<int> fa;
	void init(int n)
	{
		fa.resize(n);
		for(int i=1;i<n;i++)
		{
			fa[i]=i;
		}
	}
	int find(int x)
	{
		return fa[x]==x?x:fa[x]=find(fa[x]);
	}
};
struct ask{
	int l,r,x,ql,qr;
};
struct node{
	vector<int> blk,id;
};
vector<ask> q;
bool cmp(int x,int y)
{
	return q[x].x<q[y].x;
}
signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	int T=read();
	while(T--)
	{
		int n=read(),m=read(),k=read();
		q.assign(m,{0,0,0,0,0});
		vector<int> lsh;
		lsh.pb(1);
		lsh.pb(n+1);
		for(int i=0;i<m;i++)
		{
			q[i].l=read(),q[i].r=read(),q[i].x=read();
			lsh.pb(q[i].l);
			lsh.pb(q[i].r+1);
		}
		sort(lsh.begin(),lsh.end());
		lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
		int cnt=lsh.size()-1;
		for(int i=0;i<m;i++)
		{
			q[i].ql=lower_bound(lsh.begin(),lsh.end(),q[i].l)-lsh.begin();
			q[i].qr=lower_bound(lsh.begin(),lsh.end(),q[i].r+1)-lsh.begin()-1;
		}
		vector<int> ord(m);
		for(int i=1;i<m;i++)
		{
			ord[i]=i;
		}
		sort(ord.begin(),ord.end(),cmp);
		vector<int> up(cnt,k);
		dsu ds;
		ds.init(cnt+1);
		for(auto id:ord)
		{
			int cur=ds.find(q[id].ql);
			while(cur<=q[id].qr)
			{
				up[cur]=q[id].x;
				ds.fa[cur]=ds.find(cur+1);
				cur=ds.find(cur);
			}
		}
		map<int,node> mp;
		for(int i=0;i<cnt;i++)
		{
			mp[up[i]].blk.pb(i);
		}
		for(int i=0;i<m;i++)
		{
			mp[q[i].x].id.pb(i);
		}
		int ans=1;
		bool flag=1;
		for(auto &nod:mp)
		{
			int v=nod.first;
			vector<int> &blk=nod.second.blk;
			int s=blk.size();
			vector<int> mx(s+1,0);
			for(auto id:nod.second.id)
			{
				int l=lower_bound(blk.begin(),blk.end(),q[id].ql)-blk.begin()+1,r=upper_bound(blk.begin(),blk.end(),q[id].qr)-blk.begin();
				if(l>r)
				{
					flag=0;
					break;
				}
				mx[r]=max(mx[r],l);
			}
			if(!flag)break;
			if(v==1)continue;
			vector<int> dp(s+1,0);
			dp[0]=1;
			int sum=1,a=1,b=1,inv=qpow(v-1,mod-2,mod);
			int l=0,r=0;
			for(int i=1;i<=s;i++)
			{
				a=a*qpow(v-1,lsh[blk[i-1]+1]-lsh[blk[i-1]],mod)%mod;
				b=b*qpow(inv,lsh[blk[i-1]+1]-lsh[blk[i-1]],mod)%mod;
				dp[i]=(qpow(v,lsh[blk[i-1]+1]-lsh[blk[i-1]],mod)-qpow(v-1,lsh[blk[i-1]+1]-lsh[blk[i-1]],mod)+mod)%mod*sum%mod*b%mod;
				sum=sum*qpow(v,lsh[blk[i-1]+1]-lsh[blk[i-1]],mod)%mod;
				r=max(r,mx[i]);
				while(l<r)
				{
					sum=(sum-dp[l]*a%mod+mod)%mod;
					l++;
				}
			}
			ans=ans*sum%mod;
		}
		if(!flag)puts("0");
		else writech(ans,'\n');
	}
	Code by MCYYDS
}

posted @ 2026-07-11 22:15  MCYYDS  阅读(4)  评论(0)    收藏  举报