您的位置:首页 > 其它

Zoj 1610 Count the Colors (线段树+区间更新+暴力计数)

2015-07-09 23:13 477 查看
题目大意:

  有n次操作,每次都是对一根线中的一段区间进行染色(颜色并不相同),有时候后面的颜色有可能覆盖前面的颜色,问最后涂完色,能看到的颜色有几种,每种颜色有几部分?

解题思路:

  这个题目建树的时候有些不同,并不是以点为对象,而是以区间为对象,很明显是对线段树的区间进行操作,更新的时候要以区间为单位,还有就是计算每个区间出现几次的时候可以根据线段树的建树特征对树进行遍历求解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 8005;
struct node
{
int l, r, c;
int Mid()
{
return (r + l) / 2;
}
};
node tree[maxn*4];
int cnt[maxn], temp;

void Build (int root, int l, int r)
{
tree[root].l = l;
tree[root].r = r;
tree[root].c = -1;
if (l == r - 1)
return ;
Build (2*root+1, l, tree[root].Mid());
Build (2*root+2, tree[root].Mid(), r);
}
void update (int root, int l, int r, int c)
{//区间更新,
if (l==tree[root].l && tree[root].r==r)
{
tree[root].c = c;
return ;
}
if (tree[root].c != -1)
{
tree[2*root+1].c = tree[2*root+2].c = tree[root].c;
tree[root].c = -1;
}
if (l >= tree[root].Mid())
update (2*root+2, l, r, c);
else if (r <= tree[root].Mid())
update (2*root+1, l, r, c);
else
{
update (2*root+1, l, tree[root].Mid(), c);
update (2*root+2, tree[root].Mid(), r, c);
}
}
void Count (int root)
{
if (tree[root].c != -1)
{//当前区间裸露在外面
if (tree[root].c != temp)//当前区间没有被统计过
cnt[tree[root].c] ++;
temp = tree[root].c;
return ;
}
if (tree[root].l == tree[root].r-1)
{//返回未被覆盖的区间,否则会栈溢出
temp = -1;
return ;
}
Count (2*root+1);
Count (2*root+2);
}

int main ()
{
int n, m;
while (scanf ("%d", &n) != EOF)
{
Build (0, 0, maxn);

while (n --)
{
int x, y, c;
scanf ("%d %d %d", &x, &y, &c);
update (0, x, y, c);
}
temp = -1;
memset (cnt, 0, sizeof(cnt));
Count(0);
for (int i=0; i<maxn; i++)
if (cnt[i])
printf ("%d %d\n", i, cnt[i]);
printf ("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: