简单的线段树单点更新和单点取模
取模的时候暴力会超时,所以优化一下
方法如下:
维护一个线段树最大值数组, 如果 当前节点最大值 都小于 要取模的数 的话,就不向下进行取模操作(因为操作了也没啥用a,还是原来的数)
新手写题可能比较啰嗦qwq
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 100005;
long long f[N*4], maxx[N*4];
inline void pushup(int root)
{
maxx[root] = max(maxx[root*2], maxx[root*2+1]);
f[root] = f[root*2] + f[root * 2 + 1];
}
void build(int root, int left, int right)
{
if(left == right)
{
int a;
cin>>a;
f[root] = a;
maxx[root] = a;
return ;
}
int mid = (left + right) >> 1;
int rt = root << 1;
build(rt, left, mid);
build(rt + 1, mid + 1, right);
f[root] = f[rt] + f[rt + 1];
maxx[root] = max(maxx[rt], maxx[rt + 1]);
}
void update(int root, int left, int right, int pos, int val)
{
if(left == right)
{
f[root] = maxx[root] = val;
return ;
}
int mid = (left + right) >> 1;
int rt = root << 1;
if(pos <= mid)
{
update(rt, left, mid, pos, val);
}
else
{
update(rt + 1, mid + 1, right, pos, val);
}
f[root] = f[rt] + f[rt + 1];
maxx[root] = max(maxx[rt], maxx[rt + 1]);
}
void qmod(int root, int left, int right, int uleft, int uright, int mos)
{
if(left == right)
{
f[root] %= mos;
maxx[root] %= mos;
return ;
}
int mid = (left + right) >> 1;
int rt = root << 1;
if(mid >= uleft && mos <= maxx[rt])
{
qmod(rt, left, mid, uleft, uright, mos);
}
if(mid < uright && mos <= maxx[rt + 1])
{
qmod(rt + 1, mid + 1, right, uleft, uright, mos);
}
f[root] = f[rt] + f[rt + 1];
maxx[root] = max(maxx[rt], maxx[rt + 1]);
}
long long show(int root, int left, int right, int uleft, int uright)
{
if(left >= uleft && right <= uright)
{
return f[root];
}
int mid = (left + right) >> 1;
int rt = root << 1;
long long ans;
ans = 0;
if(mid >= uleft)
{
ans += show(rt, left, mid, uleft, uright);
}
if(mid < uright)
{
ans += show(rt+1, mid + 1, right, uleft, uright);
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d", &n, &m);
build(1,1,n);
while(m--)
{
int j;
scanf("%d", &j);
if(j == 1)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", show(1,1,n,l,r));
}
else if(j == 2)
{
int l,r,x;
scanf("%d%d%d", &l, &r, &x);
}
else if(j == 3)
{
int k,x;
scanf("%d%d", &k, &x);
update(1,1,n,k,x);
}
}
return 0;
}
ps:最近做线段树真的做的头皮发麻,每次写老是少点啥东西, 比如说这个,我有一个更新最大值的忘写了找了老半天orz
接着去写了886(还是没搞懂区间连续的题呜呜呜俺先从这到入手的HDOJProblem - 1540但是CSDN上的题解都看不懂...看了一天了也好猛,可以有大佬带带我嘛