题目链接:
ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study
题意概括:
对于一个序列,查询操作是给出一个区间[l, r],求
还有单点修改序列的操作
数据范围:
题解分析:
频繁的区间询问、区间修改,很明显就是线段树的题了
对每个节点,维护三个变量
- sum : 存储该序列区间所有值的和
- ans : 存储该序列区间符合题意的询问值
- cnt : 存储该序列区间中数的个数
则当向上更新,两个区间合并时的方法应该是
tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
tree[p].cnt = tree[p << 1].cnt + tree[p << 1 | 1].cnt;
tree[p].ans = tree[p << 1].ans + tree[p << 1 | 1].ans + tree[p << 1].sum * tree[p << 1 | 1].cnt;
AC代码:
#include <stdio.h>
using namespace std;
const int MAXN=1e5 + 10;
typedef long long ll;
int origin[MAXN];
struct node {
ll sum;
ll ans;
int cnt;
} tree[MAXN<<2];
void pushup(int p) {
tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
tree[p].cnt = tree[p << 1].cnt + tree[p << 1 | 1].cnt;
tree[p].ans = tree[p << 1].ans + tree[p << 1 | 1].ans + tree[p << 1].sum * tree[p << 1 | 1].cnt;
}
void build(int p, int l, int r) {
if (l == r) {
tree[p].cnt = 1;
tree[p].sum = origin[l];
tree[p].ans = origin[l];
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
pushup(p);
}
void update_node(int p, int l,int r, int q,int v) {
if (l == r) { //查询到点
tree[p].sum = v;
tree[p].ans = v;
return;
}
int mid = (l + r) >> 1;
if (q > mid) update_node(p << 1 | 1, mid + 1, r, q, v);
else update_node(p << 1, l, mid, q, v);
pushup(p);
}
node query(int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return tree[p]; //被包含在询问区域内的区间(有效的部分)
int mid = (l + r) >> 1;
node temp, tempr, templ;
tempr.cnt = tempr.sum = tempr.ans = 0;
templ.cnt = templ.sum = templ.ans = 0;
if (qr > mid) tempr = query(p << 1 | 1, mid + 1, r, ql, qr);
//分块切割出有效的部分(已忽略无效部分)
if (ql <= mid) templ = query(p << 1, l, mid, ql, qr);
temp.cnt = templ.cnt + tempr.cnt;
temp.sum = templ.sum + tempr.sum;
temp.ans = templ.ans + tempr.ans + templ.sum * tempr.cnt;
return temp;
}
int main () {
int n, q;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++)
scanf("%d", origin + i);
build(1, 1, n);
while(q--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (a == 1) {
printf("%lld\n", query(1, 1, n, b, c).ans);
}
else {
update_node(1, 1, n, b, c);
}
}
}
Ryuji doesn't want to study
Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i].
Unfortunately, the longer he learns, the fewer he gets.
That means, if he reads books from l to r, he will get a[l] × L + a[l + 1] × (L − 1) + ⋯+ a[r − 1] × 2 + a[r] (L is the length of [ l, r ] that equals to r − l + 1). Now Ryuji has q questions, you should answer him:
1. If the question type is 1, you should answer how much knowledge he will get after he reads books [ l, r ].
2. If the question type is 2, Ryuji will change the ith book's knowledge to a new value.
Input
First line contains two integers n and q (n, q ≤ 100000). The next line contains n integers represent a[i](a[i] ≤ 1e9) .
Then in next q line each line contains three integers a, b, c, if a = 1, it means question type is1, and b, c represents [ l , r ].
if a = 2 , it means question type is 2 , and b, c means Ryuji changes the bth book' knowledge to c
Output
For each question, output one line with one integer represent the answer.
样例输入
5 3
1 2 3 4 5
1 1 3
2 5 0
1 4 5
样例输出
10
8