ABC255Ex题解

[ABC255Ex] Range Harvest Query

题目大意

给定一片 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=lr,这个用等差数列公式即可。因为数据较大,所以除 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;
}

你可能感兴趣的:(题解,算法)