ZOJ->Count the Colors

题目传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

  题目意思是区间涂色,求最后能看到的颜色的段数。解法是线段树。

  建立一棵线段树,对每一条线段用点表示,比如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;
}
posted @ 2011-09-02 12:04  like@neu  阅读(209)  评论(0编辑  收藏  举报