线段树模式的题目,两个操作
1,l,r 查询a[l]*Len + a[l+1]*(Len-1) … + a[r]这个结果
2.p,v,把p位置更新为v
比赛时很早就发现这个题目可以做了。
而且自己也写过类似的题目,但时不知道为何自己比赛的时候就是不能一次的通过,队友对自己代码的不信任大概也都时来自与此吧,毕竟谁愿意相信一个经常写WA的人来去写呢。
该线段树维护一个区间和以及一个区间值(查询模式的结果)
线段树最重要的就是区间合并,对于两个区间[1,2]和[3,4],两个区间存储的分别是
a[1]*2 + a[2]和a[3]*2 + a[4].只需要原区间值加上奖前者区间和乘以后面一个区间的长度即可再加上后面的区间值。
即对于区间A和区间B.合并后的值为value(A) + value(B) + sum(A)*B.len();
注意查询的时候也要注意增加的值,我是从左往右进行查询。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX = 100010;
typedef long long ll;
#define lson (k*2)
#define rson (k*2+1)
class Node{
public:
int l,r;
ll sum;
ll value;
int len(){
return r-l+1;
}
int mid(){
return (l+r)/2;
}
};
Node tree[MAX*4];
void PushUp(int k){
int L = tree[lson].len();
int R = tree[rson].len();
tree[k].sum = tree[lson].sum + tree[rson].sum;
tree[k].value = tree[lson].value+tree[rson].value+tree[lson].sum*R;
}
void Build(int L,int R,int k){
tree[k].l = L;tree[k].r = R;
if(L == R){
ll v;
scanf("%lld",&v);
tree[k].sum = v;
tree[k].value = v;
return;
}
int mid = tree[k].mid();
Build(L,mid,lson);
Build(mid+1,R,rson);
PushUp(k);
// cout <<"k = " << k << " " << tree[k].sum << endl;
}
void Update(int p,ll v,int k){
if(tree[k].l == tree[k].r && tree[k].l == p){
tree[k].sum = v;
tree[k].value = v;
return;
}
int mid = tree[k].mid();
if(p <= mid) Update(p,v,lson);
else Update(p,v,rson);
PushUp(k);
}
ll Query(int L,int R,int k,int &len){
if(L <= tree[k].l && tree[k].r <= R){
int add = R-L+1-len-tree[k].len();
//这里表示要增加的倍数,R-L+1,表示查询区间的长度,len时已经查询的长度
ll temp = tree[k].value + add*tree[k].sum;
// printf("%d %lld\n",k,temp);
len += tree[k].len();
return temp;
}
ll res = 0;
int mid = tree[k].mid();
if(L <= mid) res += Query(L,R,lson,len);
if(R > mid) res += Query(L,R,rson,len);
return res;
}
//#define Local
int main(void){
#ifdef Local
freopen("in.txt","r",stdin);
#endif // Local
int N,M;
scanf("%d%d",&N,&M);
Build(1,N,1);
int len = 0;
for(int i=1;i<=M;++i){
int op;
scanf("%d",&op);
if(op == 1){
int l,r;
scanf("%d%d",&l,&r);
int len = 0;
printf("%lld\n",Query(l,r,1,len));
}
else{
int p;
ll v;
scanf("%d%lld",&p,&v);
Update(p,v,1);
}
}
return 0;
}