WA on sub3 第一个点。
思路就是将零散的区间合并,如果区间长度<3直接忽略,接下来将整块区间直接剖分:
设 S 为区间长度,则此区间总价值:
S=3n,value=33n S=3n+1,value=4×33n−1 S=3n+2,value=2×33n−2然后区间有时候衔接长度<3,此时做出特殊处理。
#include<bits/stdc++.h>
#define int long long
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
const int N=3e5+5,P=998244353;
int n,m,a[N],ans;
struct node{
int l,r,len;
bool operator<(const node &t)
const {return l<t.l;}
}sq[N];
vector<node>msq;
inline int fpm(int x,int y){
int res=1;
for(;y;y>>=1,(x*=x)%=P)
if(y&1)(res*=x)%=P;
return res;
}
signed main(){
cin>>n>>m;ans=1;
for(int i=1; i<=n; ++i)cin>>a[i];
for(int i=1; i<=m; ++i){
cin>>sq[i].l>>sq[i].r,sq[i].len=sq[i].r-sq[i].l+1;
if(sq[i].len<3)--i,--m;
}
sort(sq+1,sq+1+m);
int nl=sq[1].l,nr=sq[1].r;
for(int i=2; i<=m; ++i){
if(nr<sq[i].l){
msq.push_back({nl,nr,nr-nl+1});
nl=sq[i].l,nr=sq[i].r;
}else nr=max(nr,sq[i].r);
}
msq.push_back({nl,nr,nr-nl+1});
bool fl=0;
for(int i=0; i<msq.size(); ++i){
if(fl)continue;node ssq=msq[i];
if(msq[i].r-msq[i+1].l<3&&msq[i].r-msq[i+1].l>=0){
if(msq[i].len%3==0)
ssq=msq[i];
else if(msq[i+1].len%3==0){
swap(msq[i],msq[i+1]);
ssq=msq[i];
}
}
if(ssq.len%3==0)(ans*=fpm(3,ssq.len/3))%=P;
if(ssq.len%3==1)(ans*=4*fpm(3,ssq.len/3-1))%=P;
if(ssq.len%3==2)(ans*=2*fpm(3,ssq.len/3))%=P;
}
cout<<ans<<'\n';
return 0;
}