ACL Beginner Contest E.Replace Digits

旺 崽發表於2020-10-01

ACL Beginner Contest E.Replace Digits

題目連結

在這裡插入圖片描述
設計區間修改的題目通常都是線段樹~
因為線段樹一般都是求區間的和,這題因為涉及到十進位制的加減,所以我們可以存兩種線段樹,線段樹 s s s 每一位存初始值 1 1 1 10 10 10 100 100 100 ⋯ \cdots t a g tag tag 為懶惰標記,記錄每次區間修改的值,線段樹 t r e e tree tree 記錄修改後的線段樹,很明顯
t r e e [ i ] = t a g [ i ] ∗ s [ i ] tree[i]=tag[i]*s[i] tree[i]=tag[i]s[i],只要每次修改都 p u s h d o w n pushdown pushdown 下去即可,AC程式碼如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const ll mod=998244353;

int n,m,q,x,y;
ll k,a[N],tree[N<<2],tag[N<<2],s[N<<2];
void pushup(int i)
{
    tree[i]=(tree[i<<1]+tree[i<<1|1])%mod;
    s[i]=(s[i<<1]+s[i<<1|1])%mod;
}

void pushdown(int i){
    if(tag[i]){
        tag[i<<1]=tag[i<<1|1]=tag[i];
        tree[i<<1]=tag[i]*s[i<<1]%mod;
        tree[i<<1|1]=tag[i]*s[i<<1|1]%mod;
        tag[i]=0;
    }
}

void build(int i,int l,int r)
{
    tag[i]=0;
    if(l==r)
    {
        tree[i]=s[i]=a[l];
        return ;
    }
    int mid=l+(r-l)/2;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    pushup(i);
}

void update(int i,int l,int r,int m,int n,ll k)
{
    if(m<=l&&r<=n)
    {
        tree[i]=s[i]*k%mod;
        tag[i]=k;
        return ;
    }
    pushdown(i);
    int mid=l+(r-l)/2;
    if(m<=mid) update(i<<1,l,mid,m,n,k);
    if(n>mid) update(i<<1|1,mid+1,r,m,n,k);
    tree[i]=(tree[i<<1]+tree[i<<1|1])%mod;
}

int main(){
    scanf("%d%d",&n,&q);
    a[n]=1;
    for(int i=n-1;i>=1;i--) a[i]=a[i+1]*10%mod;
    build(1,1,n);
    while(q--){
        scanf("%d%d%lld",&x,&y,&k);
        update(1,1,n,x,y,k);
        printf("%d\n",tree[1]);
    }
    return 0;
}