18.10.16 luoguP3372 线段树模板-区间更新值&求和(POJ3468 A Simple Problem with Integers)

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数加上x

2.求出某区间每一个数的和

输入输出格式

输入格式:

 

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

 

输出格式:

 

输出包含若干行整数,即为所有操作2的结果。

 

输入输出样例

输入样例#1: 
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1: 
11
8
20

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^,保证在int64/long long数据范围内)

样例说明:

  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stack>
  5 #include <string>
  6 #include <math.h>
  7 #include <queue>
  8 #include <stdio.h>
  9 #include <string.h>
 10 #include <vector>
 11 #include <fstream>
 12 #include <set>
 13 #define l(rt) rt<<1
 14 #define r(rt) (rt<<1)+1
 15 
 16 using namespace std;
 17 const int maxn = 100005;
 18 int n, m;
 19 struct node {
 20     int l, r;
 21     long long sum,inc;
 22 }tree[maxn<<3];
 23 
 24 void build(int rt,int l,int r) {
 25     tree[rt].l = l, tree[rt].r = r;
 26     tree[rt].sum = tree[rt].inc = 0;
 27     if (l == r)return;
 28     int mid = (l + r) / 2;
 29     build(l(rt), l, mid);
 30     build(r(rt), mid + 1, r);
 31 }
 32 
 33 void change(int rt,int l,int r,long inc) {
 34     if (tree[rt].l == l && tree[rt].r == r) {
 35         tree[rt].inc += inc;
 36         return;
 37     }
 38     tree[rt].sum += inc * (r - l + 1);
 39     int mid = (tree[rt].l + tree[rt].r) / 2;
 40     if (l >= mid + 1)
 41         change(r(rt), l, r,inc);
 42     else if (r <= mid)
 43         change(l(rt), l, r,inc);
 44     else {
 45         change(l(rt), l, mid,inc);
 46         change(r(rt), mid+1, r,inc);
 47     }
 48 }
 49 
 50 long long query(int rt,int l, int r) {
 51     if (tree[rt].l == l && tree[rt].r == r) {
 52         tree[rt].sum += tree[rt].inc * (tree[rt].r - tree[rt].l + 1);
 53         tree[r(rt)].inc += tree[rt].inc;
 54         tree[l(rt)].inc += tree[rt].inc;
 55         tree[rt].inc = 0;
 56         return tree[rt].sum;
 57     }
 58     tree[rt].sum += tree[rt].inc * (tree[rt].r-tree[rt].l+1);
 59     tree[r(rt)].inc += tree[rt].inc;
 60     tree[l(rt)].inc += tree[rt].inc;
 61     tree[rt].inc = 0;
 62     int mid = (tree[rt].l + tree[rt].r) / 2;
 63     if (l > mid)
 64         return query(r(rt), l, r);
 65     else if (r <= mid)
 66         return query(l(rt), l, r);
 67     else
 68         return query(l(rt), l, mid) + query(r(rt), mid + 1, r);
 69 }
 70 
 71 void init() {
 72     scanf("%d%d", &n, &m);
 73     build(1, 1, n);
 74     for (int i = 1; i <= n; i++) {
 75         int x;
 76         scanf("%d", &x);
 77         change(1, i, i, x);
 78     }
 79     while (m--) {
 80         int oper;
 81         scanf("%d", &oper);
 82         if (oper == 1) {
 83             int x, y, k;
 84             scanf("%d%d%d", &x, &y, &k);
 85             change(1, x, y, k);
 86         }
 87         else if (oper == 2) {
 88             int x, y;
 89             scanf("%d%d", &x, &y);
 90             long long ans = query(1,x, y);
 91             printf("%lld\n", ans);
 92         }
 93     }
 94 }
 95 
 96 int main()
 97 {
 98     init();
 99     return 0;
100 }
View Code

是上课时的例题

因为睡着了所以做一遍

WA点:

一开始把 query() 函数中更新 tree[rt].sum 的值时 tree[rt].inc 乘上的值写成了 r-l+1 ,显然是错误的……手误

貌似 r(rt) 的表达式中必须加括号

大致思路:延迟更新,避免TLE

posted @ 2018-10-16 17:06  TobicYAL  阅读(198)  评论(0编辑  收藏  举报