给定一片 N N N 格的农田,从第 0 0 0 天开始,第 i i i 格农田每天会长出 i i i 的作物。
给出 Q Q Q 个询问,每次询问以 D , L , R D,L,R D,L,R 的格式给出,表示询问在第 D D D 天,收割 [ L , R ] [L,R] [L,R] 的农田,会获得多少作物?答案对 998244353 998244353 998244353 取模。注意询问相互依赖,即在每一次收割后, [ L , R ] [L,R] [L,R] 的作物应当清零。
考虑用珂朵莉数来维护当前农田最后一次被割的天数。因为每个农田增长的作物是固定的,所以我们用天数 × \times ×农田增长的总和,也就是求 ∑ i = l r \displaystyle\sum_{i=l}^r i=l∑r,这个用等差数列公式即可。因为数据较大,所以除 2 2 2要改为 × 2 \times2 ×2的逆元。
#include
using namespace std;
long long n,q,mod=998244353,inv=499122177;
struct node
{
long long l,r;
mutable long long v;
node(long long L,long long R=-1,long long V=0)
{
l=L,r=R,v=V;
}
bool operator<(const node &a) const
{
return l<a.l;
}
};
set<node> a;
#define at set<node>::iterator
long long read()
{
long long s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
at split(long long pos)
{
at it=a.lower_bound(pos);
if(it!=a.end()&&it->l==pos)
return it;
it--;
long long l=it->l;
long long r=it->r;
long long v=it->v;
a.erase(it);
a.insert(node(l,pos-1,v));
return a.insert(node(pos,r,v)).first;
}
long long emerge(long long l,long long r,long long k)
{
at itr=split(r+1);
at itl=split(l);
long long ans=0;
for(at it=itl;it!=itr;++it)
{
ans+=(k-it->v)%mod*((it->l+it->r)%mod)%mod*((it->r-it->l+1)%mod)%mod*inv%mod;
if(ans>=mod)
ans-=mod;
}
a.erase(itl,itr);
a.insert(node(l,r,k));
return ans;
}
int main()
{
n=read(),q=read();
a.insert(node(1,n,0));
for(int i=1;i<=q;++i)
{
long long k=read(),l=read(),r=read();
printf("%lld\n",emerge(l,r,k));
// for(at it=a.begin();it!=a.end();++it)
// cout<l<<" "<r<<" "<v<<"\n";
}
return 0;
}