版权声明:欢迎大家指正错误,有不同观点的欢迎评论,共同进步 https://blog.csdn.net/Sirius_han/article/details/81591298
The Child and Sequence
题意:一共n个数,三种操作:1 l r :求区间[l, r]的和; 2 l r x :将区间[l, r]的所有数对x取模; 3 k x:将k处的数改为x;
思路:如果区间的最大值都比要取模的数小,就不需要继续向下更新了,如果大,就看做单点更新;至于为什么不会T,恕在下太菜,不会证明,有兴趣可以看看这篇博客戳这里,虽然我并没有看懂,但觉有好像有那么点意思;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node{
int l, r;
ll sum, maxx;
}tr[maxn<<2];
void pushup(int m){
tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
tr[m].maxx=max(tr[m<<1].maxx, tr[m<<1|1].maxx);
}
void build(int m, int l, int r){
tr[m].l=l;
tr[m].r=r;
if(l==r){
scanf("%lld", &tr[m].sum);
tr[m].maxx=tr[m].sum;
return;
}
int mid=(l+r)>>1;
build(m<<1, l, mid);
build(m<<1|1, mid+1, r);
pushup(m);
}
void updata1(int m, int l, int r, ll mod){
if(tr[m].maxx<mod) return;
if(tr[m].l==tr[m].r){
tr[m].sum%=mod;
tr[m].maxx=tr[m].sum;\
return;
}
int mid=(tr[m].l+tr[m].r)>>1;
if(r<=mid) updata1(m<<1, l, r, mod);
else if(l>mid) updata1(m<<1|1, l, r, mod);
else{
updata1(m<<1, l, mid, mod);
updata1(m<<1|1, mid+1, r, mod);
}
pushup(m);
}
void updata2(int m, int inx, int k){
if(tr[m].l==tr[m].r){
tr[m].sum=k;
tr[m].maxx=k;
return;
}
int mid=(tr[m].l+tr[m].r)>>1;
if(inx<=mid) updata2(m<<1, inx, k);
else updata2(m<<1|1, inx, k);
pushup(m);
}
ll query(int m, int l, int r){
if(tr[m].l==l&&tr[m].r==r){
return tr[m].sum;
}
int mid=(tr[m].l+tr[m].r)>>1;
ll temp;
if(r<=mid) temp=query(m<<1, l, r);
else if(l>mid) temp=query(m<<1|1, l, r);
else{
temp=query(m<<1, l, mid)+query(m<<1|1, mid+1, r);
}
pushup(m);
return temp;
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
build(1, 1, n);
while(m--){
int type;
scanf("%d", &type);
if(type==1){
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", query(1, l, r));
}
else if(type==2){
int l, r;
ll x;
scanf("%d%d%lld", &l, &r, &x);
updata1(1, l, r, x);
}
else{
int inx;
ll k;
scanf("%d%lld", &inx, &k);
updata2(1, inx, k);
}
}
return 0;
}