【题解】[Codeforces 438D] The Child and Sequence【线段树 均摊数据结构】

题目链接

题意

维护序列:

  • 区间求和;
  • 单点加;
  • 区间开根并下取整。

(n,mleq 10^5)(a_ileq 10^9)

题解

注意到开根并下取整的操作会很快让 (a_i) 变为 (1)。因此维护区间最大值,对于操作 3,(max a_{[l..r]}=1) 则忽略,否则暴力递归修改。

复杂度 (O(nlog nlog a_i))

#include<cstdio>
#include<iostream>
using namespace std;

const int BUF_LEN=1<<19;
struct FastIO{
    char bufi[BUF_LEN+10],*PTi=bufi+BUF_LEN,*PTENDi=bufi+BUF_LEN;
    inline char gc(){
        (PTi==PTENDi)&&(bufi[fread(bufi,1,BUF_LEN,stdin)]=0,PTi=bufi);
        return *(PTi++);
    }
    char bufo[BUF_LEN+10],*PTo=bufo,*PTENDo=bufo+BUF_LEN;
    inline void pc(char c){
        (PTo==PTENDo)&&(fwrite(bufo,1,BUF_LEN,stdout),PTo=bufo);
        *(PTo++)=c;
    }
    void flush(){
        fwrite(bufo,1,PTo-bufo,stdout);
        PTo=bufo;
    }
    ~FastIO(){
        flush();
    }

    template<class T>inline void getint(T &x=0){
        char c=gc();
        int f=1;x=0;
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;
            c=gc();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0'; 
            c=gc();
        }
        if(f==-1)x=-x;
    }
    operator int(){
        int v;getint(v);return v;
    }
    operator long long(){
        long long v;getint(v);return v;
    }
    template<class T>inline void putint(T x=0,char sep=' '){
        char tmp[20],len=0;
        if(x<0)pc('-'),x=-x;
        if(x==0){ pc('0');pc(sep);return; }
        while(x)tmp[len++]=x%10,x/=10;
        for(int i=len-1;~i;--i)pc(tmp[i]|'0');
        pc(sep);
    }
}io;
#define ll long long
const int N=1e5+10;
int t[N<<2];
ll tt[N<<2];
void pushup(int x){ t[x]=max(t[x<<1],t[x<<1|1]); tt[x]=tt[x<<1]+tt[x<<1|1]; }
void modify(int l,int r,int k,int x,int nl,int nr){
    if(nr<l||nl>r)return;
    if(l<=nl&&nr<=r){
        if(nl==nr){
            t[x]%=k;
            tt[x]%=k;
            return;
        }
        int mid=nl+nr>>1;
        if(t[x<<1]>=k)modify(l,r,k,x<<1,nl,mid);
        if(t[x<<1|1]>=k)modify(l,r,k,x<<1|1,mid+1,nr);
        pushup(x);
    }else{
        int mid=nl+nr>>1;
        modify(l,r,k,x<<1,nl,mid);
        modify(l,r,k,x<<1|1,mid+1,nr);
        pushup(x);
    }
}
void modify(int p,int v,int x,int l,int r){
    if(l==r){t[x]=tt[x]=v;return;}
    int mid=l+r>>1;
    if(p<=mid)modify(p,v,x<<1,l,mid);
    else modify(p,v,x<<1|1,mid+1,r);
    pushup(x);
}
ll query(int l,int r,int x,int nl,int nr){
    if(nr<l||nl>r)return 0;
    if(l<=nl&&nr<=r)return tt[x];
    int mid=nl+nr>>1;
    return query(l,r,x<<1,nl,mid)+query(l,r,x<<1|1,mid+1,nr);
}
int a[N];
void build(int x,int l,int r){
    if(l==r){
        t[x]=tt[x]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    pushup(x);
}

int main(){
    int n=io,m=io;
    for(int i=1;i<=n;i++)a[i]=io;
    build(1,1,n);
    while(m--){
        int op=io;
        if(op==1){
            int l=io,r=io;
            io.putint(query(l,r,1,1,n),'
');
        }
        if(op==2){
            int l=io,r=io,k=io;
            modify(l,r,k,1,1,n);
        }
        if(op==3){
            int p=io,v=io;
            modify(p,v,1,1,n);
        }
    }
}

原文地址:https://www.cnblogs.com/wallbreaker5th/p/14251337.html