[Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】
生活随笔
收集整理的這篇文章主要介紹了
[Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:CF Round #254 div1 C
?
題目分析
這道題目是要實現區間賦值的操作,同時還要根據區間中原先的值修改區間上的屬性權值。
如果直接使用普通的線段樹區間賦值的方法,當一個節點表示的區間完全被要求修改的區間包含時,就直接打上賦值的標記然后 return 。但是這樣這個節點中每個位置原先的值不同,需要進行的屬性權值修改也就不同,是不能直接實現的。如果我們在節點表示的區間被修改的區間包含時,并不直接打標記 return ,而是當節點表示的區間被修改的區間完全包含而且這個節點中的每個位置的顏色相同時,才直接打標記然后 return ,否則就繼續遞歸下去。這樣就可以直接打標記修改屬性權值了。但是這樣看起來是會使復雜度退化的,但是實際上通過一些我不懂的勢能分析,這樣修改復雜度還是 O(log n) 的。所以這樣這道題就變成線段樹水題了。
需要維護一下每個節點表示的區間是否顏色相同。
區間賦值的題目就可以使用這種修改方式。
?
代碼
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm>using namespace std;typedef long long LL;inline int Abs(int x) {return x < 0 ? -x : x;}const int MaxN = 100000 + 5;int n, m; int Col[MaxN * 4], Len[MaxN * 4], Pc[MaxN * 4];LL T[MaxN * 4], D[MaxN * 4];bool Same[MaxN * 4];inline void Update(int x) {Same[x] = Same[x << 1] && Same[x << 1 | 1] && Col[x << 1] == Col[x << 1 | 1];if (Same[x]) Col[x] = Col[x << 1]; T[x] = T[x << 1] + T[x << 1 | 1];Len[x] = Len[x << 1] + Len[x << 1 | 1]; }inline void Add(int x, LL Num) {D[x] += Num;T[x] += (LL)Len[x] * Num; }inline void PushDown(int x) {if (D[x] != 0){Add(x << 1, D[x]);Add(x << 1 | 1, D[x]);D[x] = 0;}if (Pc[x] != 0){Col[x << 1] = Pc[x << 1] = Pc[x];Col[x << 1 | 1] = Pc[x << 1 | 1] = Pc[x];Pc[x] = 0;} }void Build(int x, int s, int t) { if (s == t){Same[x] = true;Col[x] = s;T[x] = D[x] = Pc[x] = 0;Len[x] = 1;return;}int m = (s + t) >> 1;Build(x << 1, s, m);Build(x << 1 | 1, m + 1, t);Update(x); }void Change(int x, int s, int t, int l, int r, int Num) {if (l <= s && r >= t && Same[x]){int Temp = Abs(Col[x] - Num);D[x] += (LL)Temp;T[x] += (LL)Temp * (LL)Len[x];Col[x] = Pc[x] = Num; return;}PushDown(x);int m = (s + t) >> 1;if (l <= m) Change(x << 1, s, m, l, r, Num);if (r >= m + 1) Change(x << 1 | 1, m + 1, t, l, r, Num);Update(x); }LL Query(int x, int s, int t, int l, int r) {if (l <= s && r >= t) return T[x];PushDown(x);int m = (s + t) >> 1;LL ret = 0;if (l <= m) ret += Query(x << 1, s, m, l, r);if (r >= m + 1) ret += Query(x << 1 | 1, m + 1, t, l, r);return ret; }int main() {scanf("%d%d", &n, &m); Build(1, 1, n); int f, l, r, Num;for (int i = 1; i <= m; ++i){scanf("%d%d%d", &f, &l, &r);if (f == 1) {scanf("%d", &Num);Change(1, 1, n, l, r, Num);}else printf("%I64d\n", Query(1, 1, n, l, r));}return 0; }
轉載于:https://www.cnblogs.com/JoeFan/p/4531606.html
總結
以上是生活随笔為你收集整理的[Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ARM汇编编程基础之一 —— 寄存器
- 下一篇: [ZT]图像处理库的比较:OpenCV,