The Child and Sequence(ds,思维玄学)
题目链接
题目描述
有一个长度为 \(n\) 的数列 \(\{a_n\}\) 和 \(m\) 次操作,操作内容如下:
- 格式为
1 l r
,表示求 \(\sum \limits _{i=l}^{r} a_i\) 的值并输出。 - 格式为
2 l r x
,表示对区间 \([l,r]\) 内每个数取模,模数为 \(x\)。 - 格式为
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();
}
标签:rt,Sequence,int,seg,mm,lt,Child,ds,mod
From: https://www.cnblogs.com/shi5/p/18038441