您的位置:首页 > 其它

【ZOJ】1610 Count the Colors(线段树查找隔断的线段)

2015-03-12 21:41 387 查看
题目大意:有一条最长8000的线段,其中会被最多8000种颜色分割,问一整段是全部颜色的算1,这样每种颜色有多少段呢?

这道题目一开始的思路线段树存放的自然是每一段的情况,设定-1,假如不是-1的话,就表示该段颜色都是相同的,是-1的话,表示下面颜色可以继续分。

只是在查找的时候自己犯难了,想不到怎么去将所有颜色的次数查找出来。

看了题解,这边用的想法是这样的,通过线段树的query功能,每次对分query,直到遇到一段线段是纯色的就不再往下,并且将这段加入事先的数组当中。

最后再遍历这些数组,只要这一条线段与下一条线段的颜色不一样,并且不是相连的,那么对应颜色的次数就++。就是这么暴力,直接!!

曾经竞赛不怕变形题的我,现在只能做做模板题,稍微变形就不会,这真的是因为我做题目没有以前花时间的原因吗?无奈,大学太多事了。

AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAX 8008
#define ls rt<<1
#define rs ls|1
#define m (l+r)>>1
int sum[MAX << 2];
int a[MAX];
int cnt;
struct pos
{
int l, r, c;
}p[MAX];
void ups(int rt)
{
if (sum[rt] != -1)
{
sum[ls] = sum[rt];
sum[rs] = sum[rt];
sum[rt] = -1;
}
}

void uprt(int rt)
{
if (sum[ls] == sum[rs])
sum[rt] = sum[ls];
}

void updata(int L, int R,int c, int l, int r, int rt)
{
if (L <= l&&r <= R)
{
sum[rt] = c;
return;
}
ups(rt);
int mid = m;
if (L < mid)
updata(L, R, c, l, mid, ls);
if (mid < R)
updata(L, R, c, mid, r, rs);
uprt(rt);
}

void query(int l, int r, int rt)
{
if (sum[rt] != -1)
{
p[cnt].l = l;
p[cnt].r = r;
p[cnt++].c = sum[rt];
return;
}
int mid = m;
if (l == r - 1)return;
query(l, mid, ls);
query(mid, r, rs);
}
int main()
{
int n;
int L, R,C;
while (~scanf("%d", &n))
{
memset(sum, -1, sizeof(sum));
memset(a, 0, sizeof(a));
cnt = 0;
C = 0;
int x, y, z;
for (int i = 0; i < n; i++)
{
scanf("%d%d%d", &x, &y, &z);
updata(x, y, z, 0, MAX, 1);
C = max(C, z);
}
query(0, MAX, 1);
for (int i = 0; i < cnt; i++)
{
if (i != cnt - 1 && p[i].r == p[i + 1].l&&p[i].c == p[i + 1].c)
continue;
a[p[i].c]++;
}
for (int i = 0; i <=C;i++)
if (a[i])
printf("%d %d\n", i, a[i]);
cout << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: