zoukankan      html  css  js  c++  java
  • CF438D The Child and Sequence(线段树)

    题目链接:CF原网  洛谷

    题目大意:维护一个长度为 $n$ 的正整数序列 $a$,支持单点修改,区间取模,区间求和。共 $m$ 个操作。

    $1le n,mle 10^5$。其它数均为非负整数且 $le 10^9$。


    居然被这道水题卡了那么久……

    主要难点就是取模操作。

    我们发现一个数 $x$ 模 $i(1le ile x)$:

    $ilelfloorfrac{x}{2} floor$ 时:余数小于除数,所以答案小于 $lfloorfrac{x}{2} floor$。

    $i>lfloorfrac{x}{2} floor$ 时:答案就是 $x-i$,也小于 $lfloorfrac{x}{2} floor$。

    所以 $x$ 每次被取模都至少减小一半。

    那……就是暴力线段树!

    线段树再维护一个区间最大值,当模数大于区间最大值时,直接走人。

    容易发现如果没有单点修改操作,一个叶子节点最多被暴力到 $log a_i$ 次。

    有单点修改操作?那又怎样?一共只会多 $m$ 个数而已啊!

    时间复杂度 $O((n+m)log nlog a_i)$。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        char ch=getchar();int x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,m,a[maxn],mx[maxn*4];
    ll sum[maxn*4];    //和要开long long
    inline void pushup(int o){
        sum[o]=sum[o<<1]+sum[o<<1|1];
        mx[o]=max(mx[o<<1],mx[o<<1|1]);
    }
    void build(int o,int l,int r){
        if(l==r) return void(sum[o]=mx[o]=a[l]);
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        pushup(o);
    }
    void modify(int o,int l,int r,int p,int v){
        if(l==r) return void(sum[o]=mx[o]=v);
        int mid=(l+r)>>1;
        if(mid>=p) modify(lson,p,v);
        else modify(rson,p,v);
        pushup(o);
    }
    ll query(int o,int l,int r,int ql,int qr){
        if(l>=ql && r<=qr) return sum[o];
        int mid=(l+r)>>1;ll ans=0;
        if(mid>=ql) ans+=query(lson,ql,qr);
        if(mid<qr) ans+=query(rson,ql,qr);
        return ans;
    }    //以上基本操作,不解释。。。
    void modulo(int o,int l,int r,int ql,int qr,int v){   
        if(mx[o]<v) return;    //模数大于最大值,走人
        if(l==r) return void(sum[o]=mx[o]=sum[o]%v);    //到叶子结点,暴力
        int mid=(l+r)>>1;
        if(mid>=ql) modulo(lson,ql,qr,v);    //暴力下去
        if(mid<qr) modulo(rson,ql,qr,v);
        pushup(o);
    }
    int main(){
        n=read();m=read();
        FOR(i,1,n) a[i]=read();
        build(1,1,n);
        FOR(i,1,m){
            int op=read(),x=read(),y=read();
            switch(op){
                case 1:printf("%lld
    ",query(1,1,n,x,y));break;
                case 2:modulo(1,1,n,x,y,read());break;
                case 3:modify(1,1,n,x,y);
            }
        }
    }
    线段树
  • 相关阅读:
    angular4升级angular5问题记录之this.location.back()
    angular4升级angular5问题记录之No NgModule metadata found for 'AppModule'
    Angular4图片上传预览路径不安全问题
    Angular4.0引入laydate.js日期插件方法
    Angular4.0用命令行创建组件服务出错
    IE10以下的img标签问题
    关于for循环删除数组内容出现的问题
    关于onmouseover和onmouseout的bug
    纯lua实现Base64加密与解密
    SciTE如何修改背景色
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10357640.html
Copyright © 2011-2022 走看看