poj 3468 A Simple Problem with Integers

本文从WordPress迁移而来, 查看全部WordPress迁移文章

线段树

题意:略

已经很久没有做线段树的题目了,一道简单题目复习一下。线段树的节点应该包含什么信息是由具体问题而定的,该问题涉及到区间修改和区间求和,所以设置线段树的节点信息如下

1
2
3
4
5
6
7
8
9
10
struct segment{
int l,r;
ll sum,c;
int mid(){
return (l + r) >> 1;
}
int len(){
return r - l + 1;
}
}t[4*N];

其中sum表示该区间当前的和,c表示该区间当前的增量。c其实同时肩负了两个作用,对一个区间的子区间进行了修改后,那么这个区间的增量就被破坏掉了,不是统一的,所以可以设置一个标记变量,记录该区间当前情况下增量是否统一,单增量不统一的时候,是不能传递给左右孩子区间的。但考虑我们也要记录一个区间的增量,所以干脆被增量和标记合一,单增量为0时,可能有两个意义

  1. 刚建完树,增量为0
  2. 在操作过程中增量不统一

两者意义虽然不同,但是效果是一样的,所以可以合并

因为lazy标记就派上用场了,比较简单的题目,不累述

注意会超int,用long long

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 100010
#define ll long long
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)

struct segment{
int l,r;
ll sum,c;
int mid(){
return (l + r) >> 1;
}
int len(){
return r - l + 1;
}
}t[4*N];

void build(int l ,int r,int rt){
t[rt].l = l;
t[rt].r = r;
t[rt].c = 0;
t[rt].sum = 0;
if(l == r){
scanf("%lld",&t[rt].sum);
return ;
}
int mid = t[rt].mid();
build(l,mid,lch(rt));
build(mid+1,r,rch(rt));
t[rt].sum = t[lch(rt)].sum + t[rch(rt)].sum;
}

void updata(int a , int b , ll c , int rt){
if(t[rt].l == a && t[rt].r == b){
t[rt].sum += (ll)t[rt].len() * c;
t[rt].c += c;
return ;
}
if(t[rt].c){ //lazy
t[lch(rt)].sum += (ll)t[lch(rt)].len() * t[rt].c;
t[rch(rt)].sum += (ll)t[rch(rt)].len() * t[rt].c;
t[lch(rt)].c += t[rt].c;
t[rch(rt)].c += t[rt].c;
t[rt].c = 0;
}
int mid = t[rt].mid();
if(b <= mid)
updata(a,b,c,lch(rt));
else if(a > mid)
updata(a,b,c,rch(rt));
else{
updata(a,mid,c,lch(rt));
updata(mid+1,b,c,rch(rt));
}
t[rt].sum = t[lch(rt)].sum + t[rch(rt)].sum;
}

ll query(int a ,int b , int rt){
if(t[rt].l == a && t[rt].r == b)
return t[rt].sum;

if(t[rt].c){ //lazy
t[lch(rt)].sum += (ll)t[lch(rt)].len() * t[rt].c;
t[rch(rt)].sum += (ll)t[rch(rt)].len() * t[rt].c;
t[lch(rt)].c += t[rt].c;
t[rch(rt)].c += t[rt].c;
t[rt].c = 0;
}

int mid = t[rt].mid();
if(b <= mid)
return query(a,b,lch(rt));
else if(a > mid)
return query(a,b,rch(rt));
else
return query(a,mid,lch(rt)) + query(mid+1,b,rch(rt));
}

int main(){
int n,q;
while(scanf("%d%d",&n,&q)!=EOF){
build(1,n,1);
while(q--){
int a,b;
char op[5];
scanf("%s",op);
if(!strcmp(op,"C")){
ll c;
scanf("%d%d%lld",&a,&b,&c);
updata(a,b,c,1);
}
else{
scanf("%d%d",&a,&b);
printf("%lld\n",query(a,b,1));
}
}
}
return 0;
}