ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study(树状数组)
发布时间:2022-11-04 11:07:01 204 相关标签: # c++
ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn’t want to study
题目
给一个 1e5 序列,有 1e5 次操作,每次操作有两种,1 单点修改,2 查询区间 (l, r) 值,
每个区间 【l, r】值计算过程(L 为区间长度):
一个是普通前缀和,另一个是题目中的 1 ~ n 前缀和。
求区间 【l, r】就是图中梯形减去平行四边形,也就是减去一定倍数的普通区间和。
用树状数组维护前缀和。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const int N = 1e5 + 10;
const int M = 1e2 + 5;
int n, q;
ll c1[N], c2[N], a[N];
void upd(int x, ll val){
ll t = val * (n-x+1);
while(x <= n){
c1[x] += val; // 普通前缀和
c2[x] += t; // 题目前缀和
x += (x&-x);
}
}
ll sum1(int x){
ll res = 0;
while(x > 0){
res += c1[x];
x -= (x&-x);
}
return res;
}
ll sum2(int x){
ll res = 0;
while(x > 0){
res += c2[x];
x -= (x&-x);
}
return res;
}
int main(){
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
upd(i, a[i]);
}
while(q--){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if(x == 1){
ll ans1 = sum1(z) - sum1(y-1);
ll ans2 = sum2(z) - sum2(y-1);
printf("%lld\n", ans2 - ans1 * (n - z));
}else{
ll t = z - a[y]; // 增量
a[y] = z;
upd(y, t);
}
}
return 0;
}
/*
*/
文章来源: https://blog.51cto.com/u_14130260/5816847
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报