一.题目链接:
ZOJ-1610
二.题目大意:
一条线上,端点编号为 [0, 8e3].
每次给出一段区间 和 一种颜色编号,在线上的这段区间染色.
问每种颜色出现的次数.
三.分析:
这道题(记为 Q1)与这道题(记为 Q2)不太一样
画个图理解一下:
可以看到对于 Q1 来说,[3, 4] 区间内为红色,但是节点 3 与 节点 4 相邻,此时不好判断
而 Q2 不存在这种问题,所以我们先将 Q1 转化成 Q2,然后再建树并查询即可.
注意:给的下表从 0 开始,使用时要先 +1.
四.代码实现:
#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;
const int M = (int)8e3 + 1;
struct node1
{
int l;
int r;
int w;
} tree[M * 4 + 5];
struct node2
{
int s;
int e;
};
vector <node2> v[M];
void build(int k, int l, int r)
{
tree[k].l = l;
tree[k].r = r;
tree[k].w = -1;
if(tree[k].l == tree[k].r)
return;
int mid = (tree[k].l + tree[k].r) / 2;
build(k * 2, l, mid);
build(k * 2 + 1, mid + 1, r);
}
void push(int k)
{
tree[2 * k].w = tree[k * 2 + 1].w = tree[k].w;
tree[k].w = -1;
}
void interver(int k, int l, int r, int a, int b, int c)
{
if(tree[k].l >= a && tree[k].r <= b)
{
tree[k].w = c;
return;
}
if(~tree[k].w)
push(k);
int mid = (tree[k].l + tree[k].r) / 2;
if(a <= mid)
interver(k * 2, l, mid, a, b, c);
if(mid < b)
interver(k * 2 + 1, mid + 1, r, a, b, c);
}
void query(int k, int l, int r)
{
if(~tree[k].w)
{
struct node2 t;
t.s = l;
t.e = r;
v[tree[k].w].push_back(t);
return;
}
if(tree[k].l == tree[k].r)
return;
int mid = (tree[k].l + tree[k].r) / 2;
query(k * 2, l, mid);
query(k * 2 + 1, mid + 1, r);
}
void init()
{
for(int i = 0; i < M; ++i)
v[i].clear();
}
int main()
{
int n;
while(~scanf("%d", &n))
{
init();
build(1, 1, M);
for(int i = 0; i < n; ++i)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
interver(1, 1, M, a + 1, b, c);
}
query(1, 1, M);
for(int i = 0; i < M; ++i)
{
int len = v[i].size();
if(len)
{
int cnt = 1;
for(int j = 1; j < len; ++j)
{
if(v[i][j - 1].e + 1 != v[i][j].s)
cnt++;
}
printf("%d %d\n", i, cnt);
}
}
printf("\n");
}
return 0;
}