ZOJ1610 线段树

Description

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.

 

Input



The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

 

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

 

Output



Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

 

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.

 

Sample Input



5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1

 

 

Sample Output



1 1
2 1
3 1

 

1 1

0 2
1 1

 

 题意:
0~8000长的线段,有n个染色操作,每次染[a,b]区间(染线段,不是染点),问最后没有被覆盖的颜色有多少,他们各有几个区间段。
代码:
复制代码
//类似于贴海报的题,可以把每个染色区间左值+1,变成不连续,这样就可以看成点了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=8003;
int val[maxn*4],num[maxn],n,last;
void Pushdown(int rt)
{
    if(val[rt]!=-1)
        val[rt<<1]=val[rt<<1|1]=val[rt];
    val[rt]=-1;
}
void Update(int ql,int qr,int c,int l,int r,int rt)
{
    if(ql<=l&&qr>=r){
        val[rt]=c;
        return;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    if(ql<=m) Update(ql,qr,c,l,m,rt<<1);
    if(qr>m) Update(ql,qr,c,m+1,r,rt<<1|1);
}
void Query(int l,int r,int rt)
{
    if(l==r){//算颜色段
        if(val[rt]!=-1&&val[rt]!=last)
            num[val[rt]]++;
        last=val[rt];
        return;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    Query(l,m,rt<<1);
    Query(m+1,r,rt<<1|1);
}
int main()
{
    while(scanf("%d",&n)==1){
        memset(val,-1,sizeof(val));
        memset(num,0,sizeof(num));
        int a,b,c;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&a,&b,&c);
            if(a<b) Update(a+1,b,c,1,8000,1);//判断!
        }
        last=-1;
        Query(1,8000,1);
        for(int i=0;i<=8000;i++){
            if(num[i]) printf("%d %d\n",i,num[i]);
        }
        printf("\n");
    }
    return 0;
}
复制代码

 

posted @   luckilzy  阅读(1778)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示