[清华集训 2017] 某位歌姬的故事
题目大意
给定 \(n\) 和 \(m\),同时给定 \(q\) 条形如 \((l_i,r_i,m_i)\) 的限制,求满足以下条件的长度为 \(n\) 的数组 \(a\) 的个数:
-
\(\displaystyle\forall 1\leq i\leq n\),有 \(1\leq a_i \leq m\)。
-
\(\displaystyle\forall 1\leq i\leq q\),有 \(\max_{i=l_i}^{r_i} a_i = m_i\)。
数据范围
-
\(1\leq n,m\leq 8\times 10^7\)。
-
\(1\leq q\leq 10^5\)。
题解
首先离散化,其次可以通过使用任意的数据结构求得每个位置取值的上界,即 \(lim_i=\min\{m_j|1\leq j\leq q\wedge l_j\leq i\leq r_j\}\)。
不难发现,询问 \(i\) 的结果仅和 \(lim_j=m_i\) 的 \(j\) 有关,于是将 \(m_i\) 和 \(lim_j\) 相同的划分在一起做,然后就是 Intervals 了。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
const int mod=998244353;
inline void AddAs(int &x,int y){if((x+=y)>=mod) x-=mod;}
inline void SubAs(int &x,int y){if((x-=y)<0) x+=mod;}
inline void MulAs(int &x,int y){x=1ll*x*y%mod;}
inline int Add(int x,int y){if((x+=y)>=mod) x-=mod;return x;}
inline int Sub(int x,int y){if((x-=y)<0) x+=mod;return x;}
inline int Mul(int x,int y){return 1ll*x*y%mod;}
inline int QPow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
#define Inv(x) QPow(x,mod-2)
int ql[N],qr[N],qk[N],n,m,q,tot,num;
vector<int> val,tmp;
inline void Disc(){
for(int i=1;i<=q;i++){
val.push_back(ql[i]);
val.push_back(qr[i]+1);
tmp.push_back(qk[i]);
}
val.push_back(0);
val.push_back(1);
val.push_back(n+1);
tmp.push_back(0);
tmp.push_back(m+1);
sort(val.begin(),val.end());
sort(tmp.begin(),tmp.end());
val.erase(unique(val.begin(),val.end()),val.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
tot=val.size()-2;
num=tmp.size()-1;
for(int i=1;i<=q;i++){
ql[i]=lower_bound(val.begin(),val.end(),ql[i])-val.begin();
qr[i]=upper_bound(val.begin(),val.end(),qr[i])-val.begin()-1;
qk[i]=lower_bound(tmp.begin(),tmp.end(),qk[i])-tmp.begin();
}
}
int lim[N];
vector<int> st[N],ed[N],pnt[N],qry[N];
inline void GetLim(){
for(int i=1;i<=q;i++) st[ql[i]].push_back(i);
for(int i=1;i<=q;i++) ed[qr[i]].push_back(i);
priority_queue<int> p,r;
p.push(-num);
for(int i=1;i<=tot;i++){
for(int j:st[i]) p.push(-qk[j]);
while(r.size()&&p.top()==r.top()) p.pop(),r.pop();
lim[i]=-p.top();
for(int j:ed[i]) r.push(-qk[j]);
}
for(int i=1;i<=tot;i++) pnt[lim[i]].push_back(i);
for(int i=1;i<=q;i++) qry[qk[i]].push_back(i);
}
int f[N],lp[N];
inline int Work(int k){
if(tmp[k]==1) return 1;
const int n=pnt[k].size();
pnt[k].insert(pnt[k].begin(),0);
for(int i=0;i<=n;i++) lp[i]=-1;
for(int i:qry[k]){
int l=lower_bound(pnt[k].begin(),pnt[k].end(),ql[i])-pnt[k].begin();
int r=upper_bound(pnt[k].begin(),pnt[k].end(),qr[i])-pnt[k].begin()-1;
if(l>r) return 0;
lp[r]=max(lp[r],l);
}
int sum=f[0]=1,tag=1;
for(int i=1,j=0;i<pnt[k].size();i++){
int w0=QPow(tmp[k]-1,val[pnt[k][i]+1]-val[pnt[k][i]]);
int w1=Sub(QPow(tmp[k],val[pnt[k][i]+1]-val[pnt[k][i]]),w0);
MulAs(tag,w0);
f[i]=Mul(Inv(tag),Mul(sum,w1));
MulAs(sum,w0);
AddAs(sum,Mul(f[i],tag));
while(j<lp[i]) SubAs(sum,Mul(f[j++],tag));
}
return sum;
}
inline void Clear(){
val.clear();
tmp.clear();
for(int i=1;i<=tot;i++){
st[i].clear();
ed[i].clear();
f[i]=lp[i]=0;
}
for(int i=1;i<=num;i++){
pnt[i].clear();
qry[i].clear();
}
}
signed main(){
int T;
cin>>T;
while(T--){
cin>>n>>q>>m;
for(int i=1;i<=q;i++) cin>>ql[i]>>qr[i]>>qk[i];
Disc();
int ans=1;
GetLim();
// for(int i=1;i<=tot;i++) cout<<val[i]<<' ';cout<<endl;
// for(int i=1;i<=tot;i++) cout<<lim[i]<<' ';cout<<endl;
for(int i=1;i<num;i++) MulAs(ans,Work(i));
for(int i:pnt[num]) MulAs(ans,QPow(m,val[i+1]-val[i]));
Clear();
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号