类型:一维线段树
来源:ZOJ Monthly, May 2003
题目:线段染色问题,求最后最上面的颜色段数思路:对每一次染色执行update操作,当颜色未完全覆盖当前段时,当前根的颜色块需要下移!然后执行一次query操作记录所有线段的颜色
数据:2
1 2 3
4 5 3结果为2
// zoj 1610
// tle wa wa wa ac 90ms
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define CLR(a,b) memset(a,b,sizeof(a))
const int MAXN = 8010;
const int MAXM = 8010;
int n, a, b, c;
int tree[4 * MAXN], cnt[MAXM], col[MAXM];
void update(int root, int l, int r, int x1, int x2) {
if(l == x1 && r == x2) {
tree[root] = c;
return ;
}
if(l == r - 1)
return ;
if(tree[root] != -1) {
tree[root << 1] = tree[root];
tree[root << 1 | 1] = tree[root];
tree[root] = -1;
}
int mid = (l + r) >> 1;
if(mid >= x2)
update(root << 1, l, mid, x1, x2);
else if(mid <= x1)
update(root << 1 | 1, mid, r, x1, x2);
else {
update(root << 1, l, mid, x1, mid);
update(root << 1 | 1, mid, r, mid, x2);
}
}
void query(int root, int l, int r) {
int i;
if(tree[root] != -1) {
FOR(i, l, r)
col[i] = tree[root];
return ;
}
if(l == r - 1)
return ;
int mid = (l + r) >> 1;
query(root << 1, l, mid);
query(root << 1 | 1, mid, r);
}
int main() {
int i;
while(scanf("%d", &n) != EOF) {
CLR(tree, -1), CLR(cnt, 0), CLR(col, -1);
int maxc = -1, maxb = -1;
FOR(i, 0, n) {
scanf("%d %d %d", &a, &b, &c);
maxc = max(maxc, c);
maxb = max(maxb, b);
update(1, 0, 8001, a, b);
}
int tmp = -1;
query(1, 0, 8001);
FOR(i, 0, maxb) {
if(col[i] == -1) {
tmp = -1;
continue;
}
if(col[i] != tmp)
++cnt[col[i]], tmp = col[i];
}
FORE(i, 0, maxc)
if(cnt[i] != 0)
printf("%d %d\n", i, cnt[i]);
printf("\n");
}
return 0;
}
/*
2
1 4000 1
4000 6000 0
2
1 2 3
4 5 3
*/