[ CodeForces 438 D ] The Child and Sequence

\(\\\)

\(Description\)


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

  • \(N,M\le 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\n",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;
}

posted @ 2018-10-13 20:07  SGCollin  阅读(156)  评论(0编辑  收藏  举报