zoukankan      html  css  js  c++  java
  • zoj_1610 Count tht Color

      经典的线段树题目,包含了线段树的插入,更新,计数,操作过程如下:

    1、[0,8000]递归建立线段树,初始时每段的颜色为-1,表示无色;

    2、每次输入,更新对应线段的颜色;

    3、在区间[0, 8000]上统计颜色>=0的区间(即为已经图色的区间),将所对应的颜色映射到数组col[]中;

    4、对col[]进行简单的操作,输出得到的颜色和所对应的区间数;

    下面以

    5

    0  4  4

    0  3  1

    3  4  2

    0  2  2

    0  2  3

    为例演示一下过程,这里简化一下,我只建立[0, 4]的线段树:

    代码+注释:

    #include <stdio.h>
    #include
    <stdlib.h>
    #include
    <string.h>
    #define L(x) (x << 1) //左孩子
    #define R(x) (x << 1 | 1) //右孩子
    #define N 8010

    struct Segment
    {
    int col;
    int l, r;
    }Segment[
    3*N];

    int col[N], len[N];

    void creat(int t, int l, int r) //递归建立线段树
    {
    Segment[t].l
    = l;
    Segment[t].r
    = r;
    Segment[t].col
    = -1;
    if(r-l == 1) return;
    int mid = (l + r) >> 1;
    creat(L(t), l, mid);
    creat(R(t), mid, r);
    }
    void updata(int t, int l, int r, int col) //更新线段树
    {
    if(Segment[t].l >= l && Segment[t].r <= r) //如果刚好是区间[l, r]
    {
    Segment[t].col
    = col;
    return ;
    }
    if(Segment[t].col == col) return ; //如果已经染过该颜色
    if(Segment[t].col >= 0) //如果是此节点已经标有颜色,则将颜色下分到此节点的左右孩子,自身颜色标为-1
    {
    Segment[L(t)].col
    = Segment[t].col;
    Segment[R(t)].col
    = Segment[t].col;
    Segment[t].col
    = -1;
    }
    int mid = (Segment[t].l + Segment[t].r) >> 1;
    if(l >= mid) updata(R(t), l, r, col); //右孩子
    else if(r <= mid) updata(L(t), l, r, col); //左孩子
    else
    {
    updata(L(t), l, mid, col);
    //右孩子
    updata(R(t), mid, r, col); //左孩子
    }
    }

    void count(int t, int l ,int r) //统计颜色
    {
    int i;
    if(Segment[t].col >= 0) //如果该节点是单色,则将给节点所对应的区间映射到数组col[i]中
    {
    for(i = l; i < r; i++)
    {
    col[i]
    = Segment[t].col;
    }
    return ;
    }
    if(Segment[t].l == Segment[t].r - 1) //如果到达最小子区间,则跳出!
    {
    return;
    }
    int mid = (Segment[t].l + Segment[t].r) >> 1;

    if(l >= mid)
    count(R(t), l , r);
    //右孩子
    else if(r <= mid)
    count(L(t), l, r);
    //左孩子
    else
    {
    count(L(t), l, mid);
    //左孩子
    count(R(t), mid, r); //右孩子
    }
    }

    int main()
    {
    int x, y, c, n, i;
    while(~scanf("%d", &n))
    {
    memset(col,
    -1, sizeof(col));
    memset(Segment ,
    0, sizeof(Segment));
    creat(
    1, 0, N);
    for(i = 0; i < n; i++)
    {
    scanf(
    "%d%d%d", &x, &y, &c);
    updata(
    1, x, y, c);
    }
    count(
    1, 0, N);
    memset(len,
    0, sizeof(len));
    for(i = 0; i < N; i++)
    if(col[i+1] != col[i] && col[i] != -1) //如果col[i+1] == c[i] 说明它俩是一个区间的,只计数一次
    len[col[i]]++;
    for(i = 0; i < N; i++)
    if(len[i])
    printf(
    "%d %d\n", i, len[i]);
    printf(
    "\n");
    }
    return 0;
    }
  • 相关阅读:
    EL表达式与JSTL
    JSP
    session
    四则运算 第二次
    第二次作业
    四则运算
    用户使用手册与测试报告
    系统设计和任务分配
    需求规格说明书和原型设计
    用户需求分析和竞品分析
  • 原文地址:https://www.cnblogs.com/vongang/p/2131881.html
Copyright © 2011-2022 走看看