題目鏈接:
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