[CF438D]The Child and Sequence:线段树+均摊复杂度

题意:

维护一个区间,满足:
1、区间求和。
2、区间取模。
3、单点修改。

分析:

看似好像是个神题,其实水的一pi。
就比如x%k,分析三种情况(此处略),发现要么x%k==x,要么x%k<=x/2。
再加上修改是单点修改,我们就可以愉快的均摊复杂度了@~@
线段树维护区间最大值和区间和。
在区间赋值时,若一个区间的最大值<模数k,直接跳过。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=100005;
int n,m,a[MAXN],maxn[MAXN<<2],ql,qr,k,loc;
LL sum[MAXN<<2];
#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
void build(int o,int l,int r){
    if(l==r){
        sum[o]=maxn[o]=a[l];
        return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
    maxn[o]=max(maxn[lc],maxn[rc]);
}
void modupd(int o,int l,int r){
    if(maxn[o]<k) return;//标重点
    if(l==r){
        sum[o]=maxn[o]=maxn[o]%k;
        return;
    }
    if(mid>=ql) modupd(lc,l,mid);
    if(mid<qr) modupd(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
    maxn[o]=max(maxn[lc],maxn[rc]);
}
void upd(int o,int l,int r){
    if(l==r&&l==loc){
        sum[o]=maxn[o]=k;
        return;
    }
    if(loc<=mid) upd(lc,l,mid);
    else upd(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
    maxn[o]=max(maxn[lc],maxn[rc]);
}
LL query(int o,int l,int r){
    if(ql<=l&&r<=qr) return sum[o];
    LL ans=0;
    if(mid>=ql) ans+=query(lc,l,mid);
    if(mid<qr) ans+=query(rc,mid+1,r);
    return ans;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int opt=read();
        if(opt==1){
            ql=read(),qr=read();
            printf("%lld\n",query(1,1,n));
        }
        else if(opt==2){
            ql=read(),qr=read(),k=read();
            modupd(1,1,n);
        }
        else{
            loc=read(),k=read();
            upd(1,1,n);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9301881.html