题意:在[0, 8000]上染色n次,每次染色的区间为[x1, x2],颜色为c,问最后每种颜色有多少段(所有数字在[0, 8000]内)。
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610
——>>对于端点x1, x2,对应成区间段[x1+1, x2],接着就染染色,线段树处理一下就好了。。。#^_^
SF了几次,原因:n指染色次数,并非指在区间[0, n]上染色。
#include <cstdio>
#include <cstring>
using namespace std;
#define lc (o<<1)
#define rc ((o<<1)+1)
const int N = 8000;
const int maxn = (8000 + 10) << 2;
int col[maxn], a[maxn], cnt[maxn];
void build(int o, int l, int r) {
col[o] = -1;
if(l == r) return;
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m+1, r);
}
void pushdown(int o) {
col[lc] = col[rc] = col[o];
col[o] = -1;
}
void update(int o, int l, int r, int ql, int qr, int v) {
if(ql <= l && r <= qr) {
col[o] = v;
return;
}
if(col[o] == v) return;
if(col[o] != -1) pushdown(o);
int m = (l + r) >> 1;
if(ql <= m) update(lc, l, m, ql, qr, v);
if(qr > m) update(rc, m+1, r, ql, qr, v);
}
void query(int o, int l, int r) {
if(col[o] != -1) {
for(int i = l; i <= r; i++) {
a[i] = col[o];
}
return;
}
if(l == r) return;
int m = (l + r) >> 1;
query(lc, l, m);
query(rc, m+1, r);
}
void solve() {
memset(cnt, 0, sizeof(cnt));
for(int i = 1; i <= N; i++) //遍历段
if(a[i] != a[i-1])
cnt[a[i]]++;
for(int i = 0; i <= N; i++) //遍历颜色
if(cnt[i])
printf("%d %d\n", i, cnt[i]);
}
int main()
{
int n, x1, x2, c;
while(scanf("%d", &n) == 1) {
build(1, 1, N);
for(int i = 0; i < n; i++) {
scanf("%d%d%d", &x1, &x2, &c);
update(1, 1, N, x1+1, x2, c);
}
memset(a, -1, sizeof(a));
query(1, 1, N);
solve();
puts("");
}
return 0;
}