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