zoukankan      html  css  js  c++  java
  • [ CodeForces 438 D ] The Child and Sequence

    (\)

    (Description)


    维护长为 (N) 的数列,(M)次操作,支持单点修改,区间取模,查询区间和。

    • (N,Mle 10^5)

    (\)

    (Solution)


    线段树单点修改直接改,直接维护区间和就好。

    关于取模,显然的优化是,当前节点代表区间最大值如果小于模数就停止递归。

    事实上我们只需要这样做,甚至连区间取模的 tag 都不用。

    因为一个数变为 (1) 至多需要 (log) 次取模,所以每个数至多被有效操作 (log) 次,然而修改是单点修改,所以并不会对区间暴力取模有太大的影响。

    (\)

    (Code)


    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100010
    #define gc getchar
    #define Rg register
    #define mid ((l+r)>>1)
    using namespace std;
    typedef long long ll;
    
    inline ll rd(){
      ll x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    ll n,m,a[N];
    
    struct segment{
    
      ll root,ptr;
    
      inline ll newnode(){return ++ptr;}
    
      struct node{ll ls,rs,sum,mx;}c[N<<2];
    
      inline void pushup(ll rt){
        c[rt].mx=max(c[c[rt].ls].mx,c[c[rt].rs].mx);
        c[rt].sum=c[c[rt].ls].sum+c[c[rt].rs].sum;
      }
    
      void build(ll &rt,ll l,ll r){
        rt=newnode();
        if(l==r){
          c[rt].mx=c[rt].sum=a[l];
          return;
        }
        build(c[rt].ls,l,mid);
        build(c[rt].rs,mid+1,r);
        pushup(rt);
      }
    
      void updata1(ll rt,ll l,ll r,ll L,ll R,ll p){
        if(r<L||l>R) return;
        if(l==r){
          c[rt].mx=c[rt].sum=c[rt].sum%p;
          return;
        }
        if(c[rt].mx<p) return;
        if(L<=mid) updata1(c[rt].ls,l,mid,L,R,p);
        if(R>mid) updata1(c[rt].rs,mid+1,r,L,R,p);
        pushup(rt);
      }
    
      void updata2(ll rt,ll l,ll r,ll p,ll x){
        if(l==r){
          c[rt].mx=c[rt].sum=x;
          return;
        }
        if(p<=mid) updata2(c[rt].ls,l,mid,p,x);
        else updata2(c[rt].rs,mid+1,r,p,x);
        pushup(rt);
      }
    
      ll query(ll rt,ll l,ll r,ll L,ll R){
        if(r<L||l>R) return 0;
        if(l>=L&&r<=R) return c[rt].sum;
        ll ans=0;
        if(L<=mid) ans+=query(c[rt].ls,l,mid,L,R);
        if(R>mid) ans+=query(c[rt].rs,mid+1,r,L,R);
        return ans;
      }
    
    }tree;
    
    int main(){
      n=rd(); m=rd();
      for(Rg ll i=1;i<=n;++i) a[i]=rd();
      tree.build(tree.root,1,n);
      for(Rg ll i=1,op,l,r,x;i<=m;++i){
        op=rd();
        if(op==1){
          l=rd(); r=rd();
          printf("%I64d
    ",tree.query(tree.root,1,n,l,r));
        }
        else if(op==2){
          l=rd(); r=rd(); x=rd();
          tree.updata1(tree.root,1,n,l,r,x);
        }
        else{
          l=rd(); x=rd();
          tree.updata2(tree.root,1,n,l,x);
        }
      }
      return 0;
    }
    
    
  • 相关阅读:
    Ubuntu -- 安装、卸载程序的命令
    nodejs基础 -- 多进程
    nodejs基础 -- express框架
    nodejs基础 -- web模块
    nodejs基础 -- 常用工具util
    nodejs基础 -- 全局对象
    nodejs基础 -- 路由
    MVC4中下拉菜单和单选框的简单设计方法
    Uploadify在MVC中使用方法案例(一个视图多次上传单张图片)
    Uploadify在MVC中使用方法案例(上传单张图片)
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9783968.html
Copyright © 2011-2022 走看看