https://www.luogu.org/problem/CF438D
题意
给定数列,区间查询和,区间取模,单点修改。
n,m小于10^5
分析
和花神那题一样,i%k运算可以考虑, i < k时, i不变,所以我们可以维护区间最大值,在给区间[l,r]中的每个元素%k的时候,只要max < k, 就直接return, 由此提速
(提醒: 千万不要用前一题(指花神)的思路解析后一题, 即使他们的做法很相像,但是也要认真写,认真想....我一开始居然维护的是这个区间中每个元素是不是全为0....这个受了花神那题的影响,不是正解, 这样会TLE
(注意: 在计算的时候一定要把long long 啊, int强制转换啊,对应好
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 190000+99
#define ll long long
int n,m;
ll a[MAX];
struct node{
ll sum, mx;
}tr[MAX<<2];
void push_up(int o) {
tr[o].sum = tr[o<<1].sum + tr[o<<1|1].sum ;
tr[o].mx = max(tr[o<<1].mx , tr[o<<1|1].mx );
}
void build(int o, int l, int r) {
if(l == r) {
tr[o].sum = a[l];
tr[o].mx = a[l];
return ;
}
int mid = (l+r)>>1;
build(o<<1, l, mid);
build(o<<1|1, mid+1, r);
push_up(o);
}
void update(int o, int l, int r, int x, int v) {
if(l == r) {
tr[o].sum = (ll)v;
tr[o].mx = (ll)v;
return ;
}
int mid = (l+r)>>1;
if(x <= mid) update(o<<1, l, mid, x, v);
else update(o<<1|1, mid+1, r, x, v);
push_up(o);
}
void optmo(int o, int l, int r, int ql, int qr, int k) {
if(tr[o].mx < k) return ;
if(l == r) {
tr[o].sum = tr[o].sum % k;
tr[o].mx = tr[o].mx % k;
return ;
}
int mid = (l+r)>>1;
if(ql <= mid) optmo(o<<1, l, mid, ql, qr, k);
if(mid < qr) optmo(o<<1|1, mid+1, r, ql, qr, k);
push_up(o);
}
ll query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return (ll)tr[o].sum ;
int mid = (l+r)>>1;
ll ans = 0;
if(ql <= mid) ans += query(o<<1, l, mid, ql, qr);
if(mid < qr) ans += query(o<<1|1, mid+1, r, ql, qr);
return ans;
}
int main() {
scanf("%d%d",&n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
build(1, 1, n);
int type, l, r, k, x;
for(int i = 1; i <= m; i++) {
scanf("%d",&type);
if(type == 1) {
scanf("%d%d",&l, &r);
printf("%lld\n",query(1, 1, n, l, r));
} else if(type == 2) {
scanf("%d%d%d",&l,&r, &k);
optmo(1, 1, n, l, r, k);
} else if(type == 3) {
scanf("%d%d",&k, &x);
update(1, 1, n, k, x);
}
}
}