您的位置:首页 > 其它

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,而且颜色和更新的颜色不同,那就应该把他的子树全部变为他的颜色再往下传递。

  这个方法还有可以优化的地方。如果更新的样色和当前的树德颜色相同就不用再往下更新。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: