ZOJ - 1610 Count the Colors(线段树区间更新,单点查询)

1、给了每条线段的颜色,存在颜色覆盖,求表面上能够看到的颜色种类以及每种颜色的段数。

2、线段树区间更新,单点查询。

但是有点细节,比如:

输入:

2

0 1 1

2 3 1

输出:

1 2

这种情况就需要处理一下,代码中把所有的左端点都+1,避免了这种情况。

3、

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define L(root) ((root) << 1)
#define R(root) (((root) << 1) + 1)

const int MAXN = 8005;

struct st
{
    // 区间范围
    int left, right;
    int flag;//-1没有颜色
} st[MAXN * 4];
int color[MAXN];//每种颜色看到的段数
// 建树代码基本不变
void build(int root, int l, int r)
{
    st[root].left = l, st[root].right = r, st[root].flag = -1;
    if (l == r)
    {
        return;
    }

    int m = l + ((r - l) >> 1);
    build(L(root), l, m);
    build(R(root), m + 1, r);
}

int query(int root, int x)//单点查询
{
    if (st[root].left == st[root].right)
    {
        return st[root].flag;
    }

    // 否则需将当前区间的“缓冲”值更新下去并修正各节点区间的总和
    if (st[root].flag!=-1)
    {
        st[L(root)].flag = st[root].flag;
        st[R(root)].flag = st[root].flag;
        st[root].flag = -1;
    }

    int m = st[root].left + ((st[root].right - st[root].left) >> 1);
    if (x <= m)
    {
        return query(L(root), x);
    }
    else
    {
        return query(R(root), x);
    }
}

void update(int root, int l, int r, int v)//区间更新
{
    // 如变更区间恰等于节点区间,只修正当前节点区间即可
    if (st[root].left == l && st[root].right == r)
    {
        st[root].flag = v;
        return;
    }

    // 否则需向下修正相关节点区间
    if (st[root].flag!=-1)
    {
        st[L(root)].flag = st[root].flag;
        st[R(root)].flag = st[root].flag;
        st[root].flag = -1;
    }

    int m = st[root].left + ((st[root].right - st[root].left) >> 1);
    if (r <= m)
    {
        update(L(root), l, r, v);
    }
    else if (l > m)
    {
        update(R(root), l, r, v);
    }
    else
    {
        update(L(root), l, m, v);
        update(R(root), m + 1, r, v);
    }
}

int main()
{
    int n,i;
    int x1,x2,c;
    int lastColor;//记录上一个颜色
    int nowColor;//当前颜色
    while(~scanf("%d",&n)){
        build(1,1,8001);
        for(i=1;i<=n;++i){
            scanf("%d%d%d",&x1,&x2,&c);
            update(1,++x1,x2,c);//++x1表示缩掉前面一点,处理了0 1 1,2 3 1这种情况,而且还符合了左端点从1开始
        }
        memset(color,0,sizeof(color));
        lastColor=-1;
        for(i=1;i<=8001;++i){
            nowColor=query(1,i);
            if(nowColor==lastColor)
                continue;
            else if(nowColor!=-1)
                ++color[nowColor];
            lastColor=nowColor;
        }
        for(i=0;i<=8001;++i)
            if(color[i])
                printf("%d %d\n",i,color[i]);
        printf("\n");
    }
    return 0;
}

时间: 2024-10-04 16:13:28

ZOJ - 1610 Count the Colors(线段树区间更新,单点查询)的相关文章

ZOJ 1610 Count the Colors(线段树,区间覆盖,单点查询)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB 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 s

ZOJ - 1610 Count the Colors 线段树区间修改

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. InputThe first line of each data set contains exactly o

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

Light OJ 1080 - Binary Simulation - (线段树区间更新 单点查询)

Description Given a binary number, we are about to do some operations on the number. Two types of operations can be here. 'I i j'    which means invert the bit from i to j (inclusive) 'Q i'    answer whether the ith bit is 0 or 1 The MSB (most signif

ZOJ 1610 Count the Colors【题意+线段树区间更新&amp;&amp;单点查询】

任意门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610 Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent

ZOJ 1610 Count the Colors (线段树成段更新)

题意 : 给出 n 个染色操作,问你到最后区间上能看见的各个颜色所拥有的区间块有多少个 分析 : 使用线段树成段更新然后再暴力查询总区间的颜色信息即可,这里需要注意的是给区间染色,而不是给点染色,所以对于区间(L, R)我们只要让左端点+1即可按照正常的线段树操作来做. #include<bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; co

ZOJ 1610 Count the Colors(线段树,但暴力未必不行)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610 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 color

PKU 2777 Count Color (线段树区间更新)

题意: 给你三个数:L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000),表示有一长度为L的板(1~L), 有T种颜色(1~T),然后有O个操作,初始板1~L的颜色为1,"C A B C"表示在区间A,B图上C颜色, "P A B" 表示询问 A,B区间有几种不同的颜色. #include <stdio.h> #include <iostr

Wikilo 1191线段树区间修改单点查询

这题也算比较容易的了. 如果哪个区间已经没有黑色的话,就不用update了,就是因为这个原因WA了2发,唉-- #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #incl

poj 2777 Count Color (线段树区间更新)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37647   Accepted: 11315 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.