Codeforces 444 C. DZY Loves Colors (线段树+剪枝)
题目链接:http://codeforces.com/contest/444/problem/C
给定一个长度为n的序列,初始时ai=i,vali=0(1≤i≤n).有两种操作:
- 将区间[L,R]的值改为x,并且当一个数从y改成x时它的权值vali会增加|x−y|.
- 询问区间[L,R]的权值和.
n≤10^5,1≤x≤10^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\n", query(1, l, r)); 95 } 96 } 97 return 0; 98 }