すきだよ

导航

atcoder abl_e

https://atcoder.jp/contests/abl/tasks/abl_e

输入 n(≤2e5) 和 q(≤2e5)。
初始有一个长为 n 的字符串 s,所有字符都是 1,s 的下标从 1 开始。
然后输入 q 个替换操作,每个操作输入 L,R (1≤L≤R≤n) 和 d (1≤d≤9)。
你需要把 s 的 [L,R] 内的所有字符替换为 d。
对每个操作,把替换后的 s 看成一个十进制数,输出这个数模 998244353 的结果。

输入
8 5
3 6 2
1 4 7
3 8 3
2 2 2
4 5 1
输出
11222211
77772211
77333333
72333333
72311333

输入
200000 1
123 456 7
输出
641437905

珂朵莉树练习题。

预处理 11...1 (i 个 1) 以及 10^i 的值,就可以套模板了,核心在于更新答案的逻辑。

比如把 111xxx 替换成 333xxx,那么 ans 增加了 (3-1)1111000。

#include<iostream>
#include<set>
using namespace std;
typedef long long ll;
ll res=0;
ll p[200005]={};
ll mp[200005]={};
int n,q;
const ll mod=998244353;
struct Node {
    int l,r;
    mutable int v;
    Node(int l,int r,int v):l(l),r(r),v(v) {}
    bool operator<(const Node &o) const {return l<o.l;}
};
set<Node>tree;
void init(int n){
    for(int j=1;j<=n;j++)
        p[j]=(p[j-1]*10+1)%mod;
    mp[0]=1;
    for(int j=1;j<=n;j++)
        mp[j]=(mp[j-1]*10)%mod;
    res=p[n];
}
auto split(int pos){
    if(pos > tree.rbegin()->r) return tree.end();
    auto it=tree.lower_bound(Node(pos,0,0));
    if(it!=tree.end()&&it->l==pos) return it;
    it--;
    int l=it->l,r=it->r,v=it->v;
    tree.erase(it);
    tree.insert(Node(l,pos-1,v));
    return tree.insert(Node(pos,r,v)).first;
}
void assign(int l,int r, int v){
    auto end=split(r+1),begin=split(l);
    for(auto it=begin;it!=end;it++){
        res=(res+mod+((p[it->r-it->l+1]*(v-it->v))%mod*mp[n-it->r])%mod)%mod;
    }
    tree.erase(begin,end);
    tree.insert(Node(l,r,v));
}
int main(){
    cin>>n>>q;
    init(n);
    tree.insert(Node(1,n,1));
    while(q--){
        int l,r,d;
        scanf("%d %d %d",&l,&r,&d);
        assign(l,r,d);
        printf("%lld\n",res);
    }
    system("pause");
}


posted on 2022-11-02 17:35  すきだよ  阅读(39)  评论(0编辑  收藏  举报