题目链接在这里
题目描述:
在一条直线上画不同颜色的线段,给出各线段的起点、终点和颜色,求画完之后,最终会有几种颜色,每个颜色有多少条线段。
思路分析:
我们用线段树保存各点的颜色,区间更新,最后query一下就好。
注意题目给的是线段的起点和终点,是连续的。如果想用离散的表示的话,就让起点+1,代表一段。
代码如下:
非结构体:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#define rep(i, n) for(int i = 0; i < n; ++i)
#define clr(x) memset(x, 0, sizeof(x))
#define rl (rt << 1)
#define rr (rt << 1 | 1)
#define llen (tree[rl].r - tree[rl].l + 1)
#define rlen (tree[rr].r - tree[rr].l + 1)
using namespace std;
const int MaxN = 10010;
int val[MaxN << 2];
int n, last;
map<int, int> ma;
void pushdown(int rt){
if(val[rt] != -1){
val[rl] = val[rr] = val[rt];
val[rt] = -1;
}
}
void update(int l, int r, int rt, int L, int R, int w){
if(L <= l && r <= R){
val[rt] = w;
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
if(L <= mid) update(l, mid, rl, L, R, w);
if(R > mid) update(mid + 1, r, rr, L, R, w);
}
void query(int l, int r, int rt){
if(l == r){
if(val[rt] != -1 && last != val[rt]){
++ma[val[rt]];
}
last = val[rt];
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
query(l, mid, rl);
query(mid + 1, r, rr);
}
int main(){
while(~scanf("%d", &n)){
memset(val, -1, sizeof(val));
ma.clear();
int a, b, c;
rep(i, n){
scanf("%d %d %d", &a, &b, &c);
if(a < b) update(1, 8000, 1, a + 1, b, c);
}
last = -1;
query(1, 8000, 1);
map<int, int>::iterator iter;
for(iter = ma.begin(); iter != ma.end(); ++iter){
printf("%d %d\n", iter->first, iter->second);
}
putchar('\n');
}
return 0;
}
结构体:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#define rep(i, n) for(int i = 0; i < n; ++i)
#define clr(x) memset(x, 0, sizeof(x))
#define rl (rt << 1)
#define rr (rt << 1 | 1)
#define llen (tree[rl].r - tree[rl].l + 1)
#define rlen (tree[rr].r - tree[rr].l + 1)
using namespace std;
const int MaxN = 10010;
struct Node{
int l, r, mid;
int mark;
}tree[MaxN << 2];
int n, last;
map<int, int> ma;
void pushdown(int rt){
if(tree[rt].mark != -1){
tree[rl].mark = tree[rr].mark = tree[rt].mark;
tree[rt].mark = -1;
}
}
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mark = -1;
tree[rt].mid = (l + r) >> 1;
if(l == r) return;
build(l, tree[rt].mid, rl);
build(tree[rt].mid + 1, r, rr);
}
void update(int l, int r, int rt, int w){
if(l <= tree[rt].l && tree[rt].r <= r){
//printf("l:%d, r:%d, mark:%d\n", tree[rt].l, tree[rt].r, w);
tree[rt].mark = w;
return;
}
pushdown(rt);
/*if(l <= tree[rt].mid) update(l, tree[rt].mid, rl, w);
if(tree[rt].mid < r) update(tree[rt].mid + 1, r, rr, w);*/
if(r <= tree[rt].mid) update(l, r, rl, w);
else if(l > tree[rt].mid) update(l, r, rr, w);
else{
update(l, tree[rt].mid, rl, w);
update(tree[rt].mid + 1, r, rr, w);
}
}
void query(int l, int r, int rt){
if(l == r){
if(tree[rt].mark != -1 && tree[rt].mark != last){
ma[tree[rt].mark]++;
}
last = tree[rt].mark;
return;
}
pushdown(rt);
query(l, tree[rt].mid, rl);
query(tree[rt].mid + 1, r, rr);
}
int main(){
while(~scanf("%d", &n)){
ma.clear();
build(1, 8000, 1);
int x, y, z;
rep(i, n){
scanf("%d %d %d", &x, &y, &z);
if(x < y) update(x + 1, y, 1, z);
}
query(1, 8000, 1);
map<int, int>:: iterator iter;
//printf("map size:%d\n", ma.size());
for(iter = ma.begin(); iter != ma.end(); ++iter)
printf("%d %d\n", iter->first, iter->second);
putchar('\n');
}
return 0;
}