ACL Beginner Contest E.Replace Digits

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;
}
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:上身试试 返回首页