标签:线段树
Description
Input
Output

Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
解题思路:
难点在于离散化,数据过大,必须进行离散化,而且不能是普通的离散化。如果两个相邻海报没有紧挨着,则在离散化的时候必须给两个海报之间留有间隔。
打个比方:(1,10)(1,4)(5,10)这组数据,普通离散化后应该为(1,4)(1,2)(3,4),那么答案应该为2。
(1,10)(1,3)(6,10)这组数据普通离散化后应该也为(1,4)(1,2)(3,4),答案也为2,可显然这题答案应该为3。问题就出在未留有间隔。
解决方案就是判断是否紧挨,若没有紧挨,就在离散化的时候往数组里面加一个数。在这里我采用的是用结构体来进行离散化。
剩下的就是求海报出现的个数问题,对线段进行着色,后贴的海报着色会覆盖之前的海报,最后统计颜色的种数即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 11111;
int x[maxn << 2], col[maxn << 4], ans, c[maxn << 2];
bool flag[maxn << 2];
struct san
{
int a, pos;
}f[maxn << 2];
bool cmp(san v, san t)
{
return v.a < t.a;
}
void PushDown(int rt)
{
if(col[rt] != 0)
{
col[rt << 1] = col[rt << 1 | 1] = col[rt];
col[rt] = 0;
}
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L <= l && R >= r)
{
col[rt] = c;
return;
}
PushDown(rt);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (m < R) update(L , R , c , rson);
}
void query(int l, int r, int rt)
{
if(col[rt] != 0)
{
if(!flag[col[rt]]) // 用flag检测该颜色是否之前出现过
{
ans++;
flag[col[rt]] = true;
}
return;
}
if(l == r)
return;
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int main()
{
int t, n, ll, rr;
scanf("%d", &t);
while(t--)
{
ans = 0;
memset(col , 0, sizeof(col));
memset(flag, false, sizeof(flag));
scanf("%d", &n);
int k = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &ll, &rr); // 用f存储左右范围的值,因此有2*n个
f[++k].a = ll;
f[k].pos = k;
f[++k].a = rr;
f[k].pos = k;
}
sort(f + 1, f + k + 1, cmp); //进行第一次排序
int t = 2 * n;
for(int i = 2; i <= 2 * n; i++)
{
if(f[i].a > f[i - 1].a + 1) //判断是否紧挨,无需考虑两者是否属于同一个海报
{
f[++t].a = f[i - 1].a + 1; // 未紧挨就加上一个紧挨的数
f[t].pos = 0; // 使其pos为0,就不会在离散化时进入有效值中
}
}
int m = 1;
c[1] = 1;
sort(f + 1, f + t + 1, cmp); // 二次排序,产生间隔
for(int i = 2; i <= t; i++) // 去重处理
{
if(f[i].a == f[i - 1]. a)
c[i] = m;
else
c[i] = ++m;
}
for(int i = 1; i <= t; i++) // 得到有效值
x[f[i].pos] = c[i];
for(int i = 1; i <= 2 * n - 1; i += 2) //进行着色
update(x[i], x[i + 1], i, 1, 4 * n, 1);
query(1, 4 * n, 1); // 求颜色种类
printf("%d\n", ans);
}
return 0;
}
Mayor's posters(线段树 + 离散化),布布扣,bubuko.com
标签:线段树
原文地址:http://blog.csdn.net/userluoxuan/article/details/38559659