#include <stdio.h>
#include <algorithm>
using namespace std;
#define lson num << 1
#define rson num << 1 | 1
#define MAXN 100005
typedef long long ll;
int a[MAXN << 1];
struct node
{
int l,r;
ll Max,sum;
}tree[MAXN << 2];
void pushup(ll rt){
tree[rt].Max = max(tree[rt << 1].Max,tree[rt << 1|1].Max);
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1|1].sum;
}
// void build(int num,int l,int r)
// {
// tree[num].l = l;
// tree[num].r = r;
// if(l == r) {
// //scanf("%I64d",&tree[num].Max);
// tree[num].sum = tree[num].Max = a[l];
// return;
// }
// int mid = (l + r) >> 1;
// build(lson,l,mid);
// build(rson,mid + 1,r);
// pushup(num);
// }
void build(ll rt,ll l ,ll r){
tree[rt].l = l , tree[rt].r = r;
if(l == r){
tree[rt].sum = tree[rt].Max = a[l];
return;
}
ll mid = (l + r) >> 1;
build(rt << 1, l , mid);
build(rt <<1|1,mid + 1,r);
pushup(rt);
}
// ll query(int num,int l,int r)
// {
// if(tree[num].l == l && tree[num].r == r) {
// return tree[num].sum;
// }
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(r <= mid) {
// return query(lson,l,r);
// }
// else if(l > mid) {
// return query(rson,l,r);
// }
// else {
// return query(lson,l,mid) + query(rson,mid + 1,r);
// }
// }
ll query(ll rt,ll l,ll r){
if(tree[rt].l == l && r == tree[rt].r){
return tree[rt].sum;
}//cout << rt << endl;
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(r <= mid) return query(rt << 1,l ,r);
else if(l > mid) return query(rt << 1|1,l,r);
else return query(rt << 1,l, mid) + query(rt << 1|1 , mid + 1, r);
}
// void update1(int num,int l,int r,int mod)
// {
// if(tree[num].Max < mod) {
// return;
// }
// if(tree[num].l == tree[num].r) {
// tree[num].Max %= mod;
// tree[num].sum %= mod;
// return;
// }
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(r <= mid) {
// update1(lson,l,r,mod);
// }
// else if(l > mid) {
// update1(rson,l,r,mod);
// }
// else {
// update1(lson,l,mid,mod),update1(rson,mid + 1,r,mod);
// }
// pushup(num);
// }
void update1(ll rt,ll l ,ll r ,ll v){
// cout << t[rt].maxx << endl;
if(v > tree[rt].Max) return;
if( tree[rt].l == tree[rt].r){
tree[rt].Max %= v; tree[rt].sum %= v;
// cout << t[rt].sum << " " << 111 << endl;
return;
}
//
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(r <= mid) update1(rt << 1,l ,r,v);
else if(l > mid) update1(rt << 1|1,l,r,v);
else update1(rt << 1,l, mid,v) , update1(rt << 1|1 , mid + 1, r,v);
pushup(rt);
}
// void update2(int num,int pos,int val)
// {
// if(tree[num].l == tree[num].r && tree[num].l == pos) {
// tree[num].sum = val;
// tree[num].Max = val;
// return;
// }
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(pos <= mid) {
// update2(lson,pos,val);
// }
// else {
// update2(rson,pos,val);
// }
// pushup(num);
// }
void update2(ll rt,ll x,ll v){
if(tree[rt].l == tree[rt].r && tree[rt].l == x){
tree[rt].Max = tree[rt].sum = v;
return;
}
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(x <= mid) update2(rt << 1,x , v);
else update2(rt << 1|1,x , v);
pushup(rt);
}
// int main(void)
// {
// int n,m;
// scanf("%d%d",&n,&m);
// for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
// build(1,1,n);
// while(m--) {
// int op,l,r,pos,x;
// scanf("%d",&op);
// if(op == 1) {
// scanf("%d%d",&l,&r);
// printf("%I64d\n",query(1,l,r));
// }
// else if(op == 2) {
// scanf("%d%d%d",&l,&r,&x);
// update1(1,l,r,x);
// }
// else {
// scanf("%d%d",&pos,&x);
// update2(1,pos,x);
// }
// }
// return 0;
// }
int main(int argc, char const *argv[])
{
ll n , m ;
scanf("%lld%lld",&n,&m);
for(ll i = 1;i <= n ; i++) scanf("%lld",&a[i]);
build(1,1,n);
//for(ll i = 1;i <= 40; i++) cout << t[i].sum << endl;
while(m--){
ll a;
scanf("%lld",&a);
if(a == 1){
ll b , c;
scanf("%lld%lld",&b,&c);
printf("%lld\n",query(1,b,c));
}else if(a == 2){
ll b ,c, pos;
scanf("%lld%lld%lld",&b,&c,&pos);
update1(1,b,c,pos);
}else{
ll b , c;
scanf("%lld%lld",&b,&c);
update2(1,b,c);
}
}
return 0;
}
线段树单点修改的本质就是区间修改
本题是对所有数取模,如果对区间和取模,必定会影响子节点,那么便只能对子节点取模
但是如果一个一个取模,便会有超时的危险
那么我们就可以利用剪枝的思想,对小于mod的数/区间,直接返回
只对大于mod的数进行取模,那么便能降低复杂度。
#include <stdio.h>
#include <algorithm>
using namespace std;
#define lson num << 1
#define rson num << 1 | 1
#define MAXN 100005
typedef long long ll;
struct node
{
int l,r;
ll Max,sum;
}tree[MAXN << 2];
void pushup(int num)
{
tree[num].Max = max(tree[lson].Max,tree[rson].Max);
tree[num].sum = tree[lson].sum + tree[rson].sum;
}
void build(int num,int l,int r)
{
tree[num].l = l;
tree[num].r = r;
if(l == r) {
scanf("%I64d",&tree[num].Max);
tree[num].sum = tree[num].Max;
return;
}
int mid = (l + r) >> 1;
build(lson,l,mid);
build(rson,mid + 1,r);
pushup(num);
}
ll query(int num,int l,int r)
{
if(tree[num].l >= l && tree[num].r <= r) {
return tree[num].sum;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(r <= mid) {
return query(lson,l,r);
}
else if(l > mid) {
return query(rson,l,r);
}
else {
return query(lson,l,mid) + query(rson,mid + 1,r);
}
}
void update1(int num,int l,int r,int mod)
{
if(tree[num].Max < mod) {
return;
}
//因为修改的是最大值,不是区间修改,所以是这个
if(tree[num].l == tree[num].r) {
tree[num].Max %= mod;
tree[num].sum %= mod;
return;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(r <= mid) {
update1(lson,l,r,mod);
}
else if(l > mid) {
update1(rson,l,r,mod);
}
else {
update1(lson,l,mid,mod),update1(rson,mid + 1,r,mod);
}
pushup(num);
}
void update2(int num,int pos,int val)
{
if(tree[num].l == tree[num].r ) {
tree[num].sum = val;
tree[num].Max = val;
return;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(pos <= mid) {
update2(lson,pos,val);
}
else {
update2(rson,pos,val);
}
pushup(num);
}
int main(void)
{
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--) {
int op,l,r,pos,x;
scanf("%d",&op);
if(op == 1) {
scanf("%d%d",&l,&r);
printf("%I64d\n",query(1,l,r));
}
else if(op == 2) {
scanf("%d%d%d",&l,&r,&x);
update1(1,l,r,x);
}
else {
scanf("%d%d",&pos,&x);
update2(1,pos,x);
}
}
return 0;
}
原文:https://www.cnblogs.com/DWVictor/p/11198271.html