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

来源:互联网 发布:comsol软件价格 编辑:程序博客网 时间:2024/04/27 16:25

题目大意:有一条最长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)>>1int 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;}}


0 0