有一块很长的画布,现在想在这块画布上画一些颜色,不过后面画的颜色会把前面画的颜色覆盖掉,现在想知道画完后这块画布的颜色分布,比如 1号颜色有几块,2号颜色有几块。。。。
分析:基本上跟帖海报是一样的,不过最后要求输出的是这种颜色的画有几块,可以按照贴海报的方式先做出来,然后对每个点进行查询,不晓得复杂度会不会太高。不过还是先试一下吧。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Lson root<<1,L,tree[root].Mid()
#define Rson root<<1|1,tree[root].Mid()+1,R
const int maxn = 80005;
struct Hook{int l, r, c;}p[maxn];
struct Tree{
int L, R;
int color;//记录颜色
int Mid(){return (L+R)/2;}
}tree[maxn*4];
int Color[maxn];
void CoverColor(int L, int R, int e)//把区间LR涂成颜色e
{
for(int i=L; i<=R; i++)
Color[i] = e;
}
void Build(int root, int L, int R)
{
tree[root].L = L, tree[root].R = R;
//0代表没有被颜色覆盖,1代表未覆盖,2代表子树有被别的颜色覆盖
tree[root].color = 0;
if(L == R)return ;
Build(Lson);
Build(Rson);
}
void Up(int root)
{
if(tree[root].L != tree[root].R)
if(tree[root<<1].color == 1 && tree[root<<1|1].color == 1)
tree[root].color = 1;
}
void Insert(int root, int L, int R, int e)
{
if(tree[root].color == 1)return ;
if(tree[root].L == L && tree[root].R == R && !tree[root].color)
{
tree[root].color = 1;
CoverColor(L, R, e);
return ;
}
tree[root].color = 2;
if(R <= tree[root].Mid())
Insert(root<<1, L, R, e);
else if(L > tree[root].Mid())
Insert(root<<1|1, L, R, e);
else
{
Insert(Lson, e);
Insert(Rson, e);
}
Up(root);
}
int main()
{
int N;
while(scanf("%d", &N) != EOF)
{
int i, ans[maxn] = {0};
for(i=1; i<=N; i++)
scanf("%d%d%d", &p[i].l, &p[i].r, &p[i].c);
Build(1, 0, maxn-1);
memset(Color, -1, sizeof(Color));
for(i=N; i>0; i--)//因为给的是紧密区间,而建的树点的,所以把左边的+1,变成点覆盖的
Insert(1, p[i].l+1, p[i].r, p[i].c);
for(i=0; i<maxn; i++)
{
if( Color[i]!=-1 && (!i || Color[i]!=Color[i-1]) )
ans[Color[i]]++;
}
for(i=0; i<maxn; i++)if(ans[i])
printf("%d %d\n", i, ans[i]);
printf("\n");
}
return 0;
}