L i n k Link Link
D e s c r i p t i o n Description Description
桌子上零散地放着若干个不同颜色的盒子,桌子的后方是一堵墙。如右图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远(输入时,由底向上,从左到右)。
I n p u t Input Input
16 //桌子长度
5 // 盒子数量
4 7
12 14
1 5
6 10
11 16
O u t p u t Output Output
4
H i n t Hint Hint
1<=n<=100000,1<=m<=100000,保证坐标范围为[1,n].
T r a i n Train Train o f of of T h o u g h t Thought Thought
用线段树做
设一个参数color,为当前区间的颜色(若只有一种,为颜色编号,否则就为-1)
C o d e Code Code
#include<cstdio>
#include<iostream>
using namespace std;
int n, b[100005], ans, m, l, r;
struct Tree
{
int l, r, colorx;
}t[400005];//定义树啦
void Build(int x, int left, int right)
{
t[x].l = left; t[x].r = right;
if (left + 1 == right) return;
int mid = (left + right) >> 1;
Build(x * 2, left, mid);
Build(x * 2 + 1, mid, right);
return;
}//建立线段树
void Ins(int x, int L, int R, int color)
{
if (L == t[x].l && R == t[x].r)
t[x].colorx = color;
else {
if (t[x].colorx >= 0)
{
t[x * 2].colorx = t[x * 2 + 1].colorx = t[x].colorx;
t[x].colorx = -1;
}//把颜色往下传
int mid = (t[x].l + t[x].r) >> 1;
if (R <= mid) Ins(x * 2, L, R, color);//全在左节点
else if (L >= mid) Ins(x * 2 + 1, L, R, color);//全在右节点
else {
Ins(x * 2, L, mid, color);
Ins(x * 2 + 1, mid, R, color);
}
}
}
void Count(int x)
{
int mid = (t[x].l + t[x].r) >> 1;
if (t[x].colorx >= 0) b[t[x].colorx] = true;
else if (t[x].l + 1 < t[x].r) {
Count(x * 2);
Count(x * 2 + 1);
}
}//统计有多少种颜色
int main()
{
int col = 0;
scanf("%d%d", &n, &m);
Build(1, 1, n);
for (int i = 1; i <= m; ++i)
{
scanf("%d%d", &l, &r);
Ins(1, l, r, ++col);
}
Count(1);
for (int i = 1; i <= col; ++i)
if (b[i] == true) ans++;//因为0不算一种颜色
printf("%d",ans);
}
我真的是智障 ,没算零还减了1.。。卡了快一晚上了。。。