|
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
/**//* 题意: 给定一个长度为N(N <= 100000)的数列Si,紧接着Q(1 <= Q <= 100000)条操作 ,每条操作将[A, B]的区间颜色改成C(权值为C),颜色C最多三种,问最后所有数 的权值总和。
解法: 线段树
思路: 线段树的区间修改,还是利用lazy思想。线段树结点维护一个Color域和一个 Count域,Color要么是-1表示当前结点有多种颜色,要么是颜色的编号,每次插入 到完全覆盖时在该结点的Color域上打上一个标记,表示当前颜色,计算当前结点的 Count值。如果当前结点的颜色和插入的颜色相同,说明不必再往下插入了。如果没 有完全覆盖,并且当前结点的颜色单一,那么直接将父亲的值传递给而两个儿子, 还是同样的道理,之前的儿子如果有lazy标记,肯定是在当前标记之前,所以直接覆 盖即可。最后通过两个儿子的权值计算当前子树的权值。 */
#include <iostream>
using namespace std;
#define maxn 100010 #define MULTIPLE_COLOR -1
struct Tree { int nColor, nCount; int son[2]; int l, r;
void clear() { son[0] = son[1] = -1; nColor = 1; nCount = r - l + 1; }
int len() { return r - l + 1; }
void TranslateToSon(); void UpdateBy(Tree* ls, Tree* rs); }T[ maxn*4 ]; int tot;
int GetID(int& root, int l, int r) { if(root == -1) { root = tot++; T[root].l = l; T[root].r = r; T[root].clear(); } return root; }
void Tree::TranslateToSon() { if(nColor != MULTIPLE_COLOR) { int mid = (l + r) >> 1; int i0 = GetID(son[0], l, mid); T[i0].nColor = nColor; T[i0].nCount = nColor * T[i0].len();
int i1 = GetID(son[1], mid+1, r); T[i1].nColor = nColor; T[i1].nCount = nColor * T[i1].len();
nColor = MULTIPLE_COLOR; } }
void Tree::UpdateBy(Tree* ls, Tree* rs){ if(ls->nColor == rs->nColor) { nColor = ls->nColor; }else { nColor = MULTIPLE_COLOR; } nCount = ls->nCount + rs->nCount; }
void Insert(int& root, int nl, int nr, int l, int r, int val) { if(l > nr || r < nl) return ;
GetID(root, l, r);
if(T[root].nColor == val) return ;
if(nl <= l && r <= nr) { T[root].nColor = val; T[root].nCount = val * (r - l + 1); return ; } T[root].TranslateToSon();
int mid = (l + r) >> 1; Insert(T[root].son[0], nl, nr, l, mid, val); Insert(T[root].son[1], nl, nr, mid+1, r, val);
T[root].UpdateBy(&T[ T[root].son[0] ], &T[ T[root].son[1] ]); }
int n, m; int main() { int t; int Case = 1; scanf("%d", &t); while(t--) { int root = -1; tot = 0; scanf("%d %d", &n, &m); Insert(root, 1, n, 1, n, 1); while(m--) { int x, y, z; scanf("%d %d %d", &x, &y, &z); Insert(root, x, y, 1, n, z); } printf("Case %d: The total value of the hook is %d.\n", Case++, T[root].nCount); } return 0; }
|