The Child and Sequence(ds,思维玄学)

The Child and Sequence(ds,思维玄学)

题目链接

Problem - E - Codeforces

题目描述

有一个长度为 \(n\) 的数列 \(\{a_n\}\)\(m\) 次操作,操作内容如下:

  1. 格式为 1 l r,表示求 \(\sum \limits _{i=l}^{r} a_i\) 的值并输出。
  2. 格式为 2 l r x,表示对区间 \([l,r]\) 内每个数取模,模数为 \(x\)
  3. 格式为 3 k x,表示将 \(a_k\) 修改为 \(x\)

\(1 \le n,m \le 10^5\)\(1\le l,r,k,x \le 10^9\)

解法

感觉这题就是很玄学,其实此题所有的难点就在于操作2,取模这个操作对于加减好像并没有好方法能够让我们快速进行。但是注意到\(k\%x<k/2\),那么对于一个数,再怎么搞,它最多被操作二进行\(log(ai)\)次,所以只需要让线段树维护区间最大值,如过\(x\)大于区间最大值,就停止,否则就下去暴力取模,毕竟每个元素最多被取模\(31\)次,那么这个做法的最大复杂度就是\(31*nlogn\)。足以通过本题。

这种思维感觉很有意思,就是发现性质后,意识到暴力必然不超过xx次,然后直接暴力做。这道题也是相同的类型。P4145 上帝造题的七分钟 2 / 花神游历各国 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

代码实现

#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define lowbit(x) (x&(-x))
#define lson l,mid,k<<1
#define rson mid+1,r,k<<1|1
#define lt k<<1
#define rt k<<1|1
using namespace std;

typedef pair<int,int> pii;

const int N=1e5+10;
typedef pair<int,int> pii;

struct segg{
    ll s,lazy,mm;
}seg[N<<2];
void build(int l,int r,int k){
    if(l==r){cin>>seg[k].s;seg[k].mm=seg[k].s;return ;}
    int mid=l+r>>1;
    build(lson),build(rson);
    seg[k].s=seg[lt].s+seg[rt].s;
    seg[k].mm=max(seg[lt].mm,seg[rt].mm);
}
void update(int l,int r,int k,int idx,int x){
    if(l==r){
        seg[k].mm=seg[k].s=x;
        return ;
    }
    int mid=l+r>>1;
    if(idx<=mid)update(lson,idx,x);
    if(idx>mid)update(rson,idx,x);
    seg[k].s=seg[lt].s+seg[rt].s;
    seg[k].mm=max(seg[lt].mm,seg[rt].mm);
}
void update1(int l,int r,int k,int x,int y,int mod){
    if(l==r){
        seg[k].s%=mod;
        seg[k].mm=seg[k].s;return ;
    }
    int mid=l+r>>1;
    if(x<=mid)if(seg[lt].mm>=mod)update1(lson,x,y,mod);
    if(y>mid)if(seg[rt].mm>=mod)update1(rson,x,y,mod);
    seg[k].s=seg[lt].s+seg[rt].s;
    seg[k].mm=max(seg[lt].mm,seg[rt].mm);
}
ll query(int l,int r,int k,int x,int y){
    if(x<=l&&r<=y)return seg[k].s;
    ll res=0;
    int mid=l+r>>1;
    if(x<=mid)res+=query(lson,x,y);
    if(y>mid)res+=query(rson,x,y);
    return res;
}
void solve(){
    int n,m;cin>>n>>m;
    build(1,n,1);
    while(m--){
        int op;cin>>op;
        if(op==1){
            int x,y;cin>>x>>y;
            cout<<query(1,n,1,x,y)<<"\n";
        }
        else if(op==2){
            int x,y,mod;cin>>x>>y>>mod;
            update1(1,n,1,x,y,mod);
        }
        else{
            int idx,x;cin>>idx>>x;
            update(1,n,1,idx,x);
        }
    }
}
signed main(){
    std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
    srand((unsigned)time(NULL));
    //int t;std::cin>>t;while(t--)
    solve();
}
posted @ 2024-02-27 21:39  magic_here_tonight  阅读(41)  评论(0)    收藏  举报