ZOJ->Count the Colors
2011-09-02 12:04
429 查看
题目传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610
题目意思是区间涂色,求最后能看到的颜色的段数。解法是线段树。
建立一棵线段树,对每一条线段用点表示,比如0-4,就表示成1 2 3 4四个点。其实不这样也行。只是这样表示更直观了。每次插入一个区间和这个区间涂的颜色。如果这个区间正好是一棵树的左右边界,就直接更新这棵树的颜色,不再往下传递。不然的话,就要往下修改,而且这棵树的颜色也要传给它的子树。比如更新区间1 2,当前这棵树的左右边界分别是1 4,而且颜色和更新的颜色不同,那就应该把他的子树全部变为他的颜色再往下传递。
这个方法还有可以优化的地方。如果更新的样色和当前的树德颜色相同就不用再往下更新。
题目意思是区间涂色,求最后能看到的颜色的段数。解法是线段树。
建立一棵线段树,对每一条线段用点表示,比如0-4,就表示成1 2 3 4四个点。其实不这样也行。只是这样表示更直观了。每次插入一个区间和这个区间涂的颜色。如果这个区间正好是一棵树的左右边界,就直接更新这棵树的颜色,不再往下传递。不然的话,就要往下修改,而且这棵树的颜色也要传给它的子树。比如更新区间1 2,当前这棵树的左右边界分别是1 4,而且颜色和更新的颜色不同,那就应该把他的子树全部变为他的颜色再往下传递。
这个方法还有可以优化的地方。如果更新的样色和当前的树德颜色相同就不用再往下更新。
#include <iostream> #include <string.h> #include <algorithm> #include <fstream> #include <string> #include <vector> #include <numeric> using namespace std; const int N = 8000; struct CNode{ int L,R; int colour; CNode * pLeft, * pRight; }; struct Last{ int S, E, colour; }; CNode Tree[N * 5]; Last x[N * 2]; int total[N + 10]; int nCount = 0, inde = 0; void BuildTree(CNode * pRoot, int L,int R) { pRoot->L = L; pRoot->R = R; pRoot->colour = -1; if (L != R) { nCount++; pRoot->pLeft = Tree + nCount; nCount++; pRoot->pRight = Tree + nCount; BuildTree(pRoot->pLeft, L, (L + R)/2); BuildTree(pRoot->pRight, (L + R) / 2 + 1,R); } } void Insert(CNode * pRoot, int u, int v, int colour) { if( pRoot->L == u && pRoot->R == v) { pRoot->colour = colour; return; } //如果本区间颜色改变就不能保留原来颜色 if (pRoot->colour > -1) { pRoot->pLeft->colour = pRoot->colour; pRoot->pRight->colour = pRoot->colour; pRoot->colour = -1; } if (v <= (pRoot->L + pRoot->R) / 2) Insert(pRoot->pLeft, u, v, colour); else if (u >= (pRoot->L + pRoot->R) / 2 + 1) Insert(pRoot->pRight, u, v, colour); else { Insert(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1, v, colour); Insert(pRoot->pLeft, u, (pRoot->L + pRoot->R) / 2, colour); } } void Query(CNode * pRoot, int s, int e) { if(s == pRoot->L && e == pRoot->R && pRoot->colour > -1) { x[inde].S = s; x[inde].E = e; x[inde++].colour = pRoot->colour; return ; } //如果已经到了叶子节点 if (s == e) return; if(e <= (pRoot->L + pRoot->R) / 2) Query(pRoot->pLeft, s, e); else if(s >= (pRoot->L + pRoot->R) / 2 + 1) Query(pRoot->pRight, s, e); else { Query(pRoot->pLeft, s,(pRoot->L + pRoot->R) / 2); Query(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1, e); } } bool cmp(Last a, Last b){ return a.S < b.S; } int main() { int n, a, b, c; int i, j; while (scanf("%d", &n) != EOF){ nCount = 0; inde = 0; BuildTree(Tree, 1, N); for (i=0; i<n; i++){ scanf("%d%d%d", &a, &b, &c); Insert(Tree, a + 1, b, c); } Query(Tree, 1, N); sort(x, x + inde, cmp); memset(total, 0, sizeof(total)); total[x[0].colour]++; for (i=1; i<inde; i++) if (x[i].colour != x[i-1].colour || x[i].S > x[i-1].E + 1){ total[x[i].colour]++; } for (i=0; i<= N; i++) if (total[i]){ printf("%d %d\n", i, total[i]); } printf("\n"); } return 0; }
相关文章推荐
- ZOJ 1610 Count the Colors(线段树——区间更新)(成段染色)
- zoj 1610_Count the Colors_线段树
- Count the Colors ZOJ - 1610
- ZOJ 1610 Count the Colors (线段树:区间染色set,整体查询)
- 【线段树】Count the Colors (zoj 1610)
- ZOJ 1610 Count the Colors(线段树——区间更新)(成段染色)
- ZOJ----1610-Count the Colors(线段树)
- zoj 1610 Count the Colors(线段树)
- ZOJ 1610 Count the Colors(线段树区间更新)
- ZOJ 1610 Count the Colors(线段树,区间覆盖,单点查询)
- ZOJ 1610 Count the Colors(线段树——区间更新)(成段染色)
- ZOJ 1610 Count the Colors(暴力或者线段树)
- zoj 1610 Count the Colors 线段树区间更新/暴力
- Count the Colors(zoj 1610)
- zoj 1610 Count the Colors 【区间覆盖 求染色段】
- zoj 1610 Count the Colors(线段树 区间更新)
- ZOJ 1610 Count the Colors (线段树-区间覆盖)
- ZOJ 1610 Count the Colors(线段树——区间更新)(成段染色)
- ZOJ 1610 Count the Colors(线段树,成段更新染色)
- ZOJ-1610 Count the Colors