zoj_1610 Count tht Color

  经典的线段树题目,包含了线段树的插入,更新,计数,操作过程如下:

1、[0,8000]递归建立线段树,初始时每段的颜色为-1,表示无色;

2、每次输入,更新对应线段的颜色;

3、在区间[0, 8000]上统计颜色>=0的区间(即为已经图色的区间),将所对应的颜色映射到数组col[]中;

4、对col[]进行简单的操作,输出得到的颜色和所对应的区间数;

下面以

5

0  4  4

0  3  1

3  4  2

0  2  2

0  2  3

为例演示一下过程,这里简化一下,我只建立[0, 4]的线段树:

代码+注释:

#include <stdio.h>
#include
<stdlib.h>
#include
<string.h>
#define L(x) (x << 1) //左孩子
#define R(x) (x << 1 | 1) //右孩子
#define N 8010

struct Segment
{
int col;
int l, r;
}Segment[
3*N];

int col[N], len[N];

void creat(int t, int l, int r) //递归建立线段树
{
Segment[t].l
= l;
Segment[t].r
= r;
Segment[t].col
= -1;
if(r-l == 1) return;
int mid = (l + r) >> 1;
creat(L(t), l, mid);
creat(R(t), mid, r);
}
void updata(int t, int l, int r, int col) //更新线段树
{
if(Segment[t].l >= l && Segment[t].r <= r) //如果刚好是区间[l, r]
{
Segment[t].col
= col;
return ;
}
if(Segment[t].col == col) return ; //如果已经染过该颜色
if(Segment[t].col >= 0) //如果是此节点已经标有颜色,则将颜色下分到此节点的左右孩子,自身颜色标为-1
{
Segment[L(t)].col
= Segment[t].col;
Segment[R(t)].col
= Segment[t].col;
Segment[t].col
= -1;
}
int mid = (Segment[t].l + Segment[t].r) >> 1;
if(l >= mid) updata(R(t), l, r, col); //右孩子
else if(r <= mid) updata(L(t), l, r, col); //左孩子
else
{
updata(L(t), l, mid, col);
//右孩子
updata(R(t), mid, r, col); //左孩子
}
}

void count(int t, int l ,int r) //统计颜色
{
int i;
if(Segment[t].col >= 0) //如果该节点是单色,则将给节点所对应的区间映射到数组col[i]中
{
for(i = l; i < r; i++)
{
col[i]
= Segment[t].col;
}
return ;
}
if(Segment[t].l == Segment[t].r - 1) //如果到达最小子区间,则跳出!
{
return;
}
int mid = (Segment[t].l + Segment[t].r) >> 1;

if(l >= mid)
count(R(t), l , r);
//右孩子
else if(r <= mid)
count(L(t), l, r);
//左孩子
else
{
count(L(t), l, mid);
//左孩子
count(R(t), mid, r); //右孩子
}
}

int main()
{
int x, y, c, n, i;
while(~scanf("%d", &n))
{
memset(col,
-1, sizeof(col));
memset(Segment ,
0, sizeof(Segment));
creat(
1, 0, N);
for(i = 0; i < n; i++)
{
scanf(
"%d%d%d", &x, &y, &c);
updata(
1, x, y, c);
}
count(
1, 0, N);
memset(len,
0, sizeof(len));
for(i = 0; i < N; i++)
if(col[i+1] != col[i] && col[i] != -1) //如果col[i+1] == c[i] 说明它俩是一个区间的,只计数一次
len[col[i]]++;
for(i = 0; i < N; i++)
if(len[i])
printf(
"%d %d\n", i, len[i]);
printf(
"\n");
}
return 0;
}
posted @ 2011-08-09 10:45  AC_Von  阅读(205)  评论(0编辑  收藏  举报