链接: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 8010
int 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;
}