Codeforces 444 C. DZY Loves Colors (线段树+剪枝)

题目链接:http://codeforces.com/contest/444/problem/C

给定一个长度为n的序列,初始时ai=i,vali=0(1in).有两种操作:

  1. 将区间[L,R]的值改为x,并且当一个数从y改成x时它的权值vali会增加|xy|.
  2. 询问区间[L,R]的权值和.

n10^5,1x10^6.

感觉这是一个比较好的考察线段树区间更新的性质。

当区间的a[i]一样时,区间更新即可,这是剪枝。

注意,lazy标记存的是增量。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int N = 1e5 + 5;
 5 struct SegTree {
 6     LL l, r, Min, Max;
 7     LL val, lazy;
 8 }T[N << 2];
 9 
10 LL Abs(LL a) {
11     return a < 0 ? -a : a;
12 }
13 
14 void pushup(int p) {
15     T[p].Min = min(T[p << 1].Min, T[(p << 1)|1].Min);
16     T[p].Max = max(T[p << 1].Max, T[(p << 1)|1].Max);
17     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
18 }
19 
20 void pushdown(int p) {
21     if(T[p].l == T[p].r) {
22         return ;
23     } else if(T[p].lazy) {
24         T[p << 1].lazy += T[p].lazy;
25         T[(p << 1)|1].lazy += T[p].lazy;
26         T[p << 1].val += T[p].lazy*(LL)(T[p << 1].r - T[p << 1].l + 1);
27         T[(p << 1)|1].val += T[p].lazy*(LL)(T[(p << 1)|1].r - T[(p << 1)|1].l + 1);
28         T[p << 1].Min = T[p << 1].Max = T[(p << 1)|1].Max = T[(p << 1)|1].Min = T[p].Min;
29         T[p].lazy = 0;
30     }
31 }
32 
33 void build(int p, int l, int r) {
34     int mid = (l + r) >> 1;
35     T[p].l = l, T[p].r = r, T[p].lazy = 0;
36     if(l == r) {
37         T[p].Max = l, T[p].Min = l;
38         T[p].val = 0;   
39         return ;
40     }
41     build(p << 1, l, mid);
42     build((p << 1)|1, mid + 1, r);
43     pushup(p);
44 }
45 
46 void update(int p, int l, int r, LL add) {
47     int mid = (T[p].l + T[p].r) >> 1;
48     pushdown(p);
49     if(l == T[p].l && T[p].r == r && T[p].Min == T[p].Max) {
50         T[p].val += (LL)Abs(add - T[p].Min)*(LL)(r - l + 1);
51         T[p].lazy += Abs(add - T[p].Max);
52         T[p].Max = T[p].Min = add;
53         return ;
54     }
55     if(r <= mid) {
56         update(p << 1, l, r, add);
57     } else if(l > mid) {
58         update((p << 1)|1, l, r, add);
59     } else {
60         update(p << 1, l, mid, add);
61         update((p << 1)|1, mid + 1, r, add);
62     }
63     pushup(p);
64 }
65 
66 LL query(int p, int l, int r) {
67     int mid = (T[p].l + T[p].r) >> 1;
68     pushdown(p);
69     if(l == T[p].l && T[p].r == r) {
70         return T[p].val;
71     }
72     if(r <= mid) {
73         return query(p << 1, l, r);
74     } else if(l > mid) {
75         return query((p << 1)|1, l, r);
76     } else {
77         return query(p << 1, l, mid) + query((p << 1)|1, mid + 1, r);
78     }
79     pushup(p);
80 }
81 
82 int main()
83 {
84     int n, m, l, r, c;
85     LL add;
86     scanf("%d %d", &n, &m);
87     build(1, 1, n);
88     while(m--) {
89         scanf("%d %d %d", &c, &l, &r);
90         if(c == 1) {
91             scanf("%lld", &add);
92             update(1, l, r, add);
93         } else {
94             printf("%lld
", query(1, l, r));
95         }
96     }
97     return 0;
98 }
原文地址:https://www.cnblogs.com/Recoder/p/5906658.html