ZOJ1610 Count the Colors(线段树区间更新)

来源:互联网 发布:最大的网络图书馆 编辑:程序博客网 时间:2024/04/27 17:53

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

题意:一块8000长度的板子,每次覆盖啊(a,b)的格子颜色为c。覆盖的时候不包括两个端点

样例解释:

5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3

1 1
2 1
3 1

5是5步操作,板子8000长度是不变的


输出为:

颜色为1的有1段,颜色为2的有1段,颜色为3的有1段


代码:

#include<iostream>  #include<cstring>  #include<cstdio>#include<cstdlib>#include<ctime>#include<queue>#include<stack>#include<algorithm>using namespace std;#define calm (l+r)/2#define lson l,m,rt*2#define rson m+1,r,rt*2+1#define maxn 8010int sum[maxn * 4];/*原本应该用一个add数组来记录是否延迟的但是对于这个题目来说,除了叶子节点的节点都是没什么用的,所以直接用这个树上的非叶子节点来表示是否延迟,节省了空间*/int ans[8010],temp[8010];inline void Pushdown(int rt){if (sum[rt]!=-1){sum[rt * 2] = sum[rt];sum[rt * 2 + 1] = sum[rt];sum[rt] = -1;//不是叶子节点,用-1表示未延迟}}void update(int L,int R,int c,int l,int r,int rt){if (L <= l&&r <= R){sum[rt] = c;//标记return;}Pushdown(rt);int m = calm;if (L <= m)update(L, R, c, lson);if (R > m)update(L, R, c, rson);}void query(int l,int r,int rt){if (l == r)//叶子结点{temp[l] = sum[rt];//记录下当前格子的颜色是什么return;}Pushdown(rt);int m = calm;query(lson);query(rson);}int main(){//freopen("D://input.txt", "r", stdin);//freopen("D://output.txt", "w", stdout);int n;while (scanf("%d", &n) != EOF){memset(ans, 0, sizeof(ans));memset(sum, -1, sizeof(sum));//build(),每次build都要建立到8000,所以直接memset也是一样的while (n--){int a, b, c;scanf("%d%d%d", &a, &b, &c);update(a + 1, b, c, 1, 8000, 1);//所有格子往后移一格,用i表示这个【i,i-1】区间}query(1,8000,1);if (temp[1] != -1)ans[temp[1]]++;/*因为往后移了一格,原本是【0,8000】,就变成【1,8001】但是因为8001是用来表示【8000,8001】这个区间的这个区间不存在,所以枚举格子时到8000就可以了*/for (int i = 2; i <= 8000; i++)//枚举格子{if (temp[i]!=-1&&temp[i] != temp[i - 1])ans[temp[i]]++;}for (int i = 0; i <= 8000; i++)//枚举颜色{if (ans[i] != 0)printf("%d %d\n", i, ans[i]);}printf("\n");}//printf("%.6lf\n",(double)clock()/CLOCKS_PER_SEC);return 0;}


0 0