CF438D The Child and Sequence(线段树区间暴力取模)

CF438D The Child and Sequence

洛谷链接

同一个思路AC四道题太爽了

题目大意:

区间求和,区间取模,单点修改。

分析:

难点在于区间取模很难实现标记下传以及合并。
思路和线段树区间暴力开根类似。维护一个区间最大值。当要取模的区间最大值比模数小时,给这个区间取模相当于没有取模;否则即使要取模,区间中的每个数都最多只会被操作 \(O(log(x))\) 次,所以单点暴力取模不会超时。

代码:

#include<bits/stdc++.h>
#define int long long
#define MAXN 100086 
using namespace std;

int a[MAXN];
inline int read() {
     int x = 0, fh = 1;
     char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            fh = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * fh;
}

struct T{
int l,r,val,maxn;
}t[MAXN*4];
int n,m;

void update(int node){
  t[node].val=t[node<<1].val+t[node<<1|1].val;
  t[node].maxn=max(t[node<<1].maxn,t[node<<1|1].maxn);
}

void build(int l,int r,int node){
    t[node].l=l;
    t[node].r=r;
    if(l==r){
        t[node].val=a[l];
        t[node].maxn=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    update(node);
}


void change(int l,int r,int node,int p,int k){
  if(l==r){
    t[node].val=k;
    t[node].maxn=k;
    return ;
  }
  int mid=(l+r)>>1;
  int ans=0;
  if(p<=mid)change(l,mid,node<<1,p,k);
  else change(mid+1,r,node<<1|1,p,k);
  update(node);
}

int ask(int l,int r,int node,int x,int y){
  if(x<=l&&r<=y){
    return t[node].val;
  }
  int ans=0;
  int mid=(l+r)>>1;
  if(x<=mid)ans+=ask(l,mid,node<<1,x,y);
  if(y>mid)ans+=ask(mid+1,r,node<<1|1,x,y);
  return ans;
}


void change_mod(int l,int r,int node,int x,int y,int p){
  if(t[node].maxn<p)return ;
  if(l==r){
    t[node].val%=p;
    t[node].maxn%=p;
    return ;
  }
  int mid=(l+r)>>1;
  if(x<=mid)change_mod(l,mid,node<<1,x,y,p);
  if(y>mid)change_mod(mid+1,r,node<<1|1,x,y,p);
  update(node);
}

signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
  cin>>a[i];
}
build(1,n,1);
int op,x,y,z,k,p;
for(int i=1;i<=m;i++){
  cin>>op>>x>>y;
  if(op==1){
    cout<<ask(1,n,1,x,y)<<'\n';
  }
  if(op==2){
    cin>>z;
    change_mod(1,n,1,x,y,z);
  }
  if(op==3){
    change(1,n,1,x,y);
  }

}
  return 0;
}

posted @ 2022-09-06 21:10  DAIANZE  阅读(27)  评论(0编辑  收藏  举报