Count the Colors(线段树之区间成段更新)

萌萌哒的传送门

这道题目是线段树区间成段更新的应用,我们只需在建立线段树时从原来的左右儿子不相连,改为相连即可以解决此类问题.

如从原来的[l,mid] , [mid + 1,r] 改为 [l,mid],[mid,r]即可;

/*********************
 * zoj1610           *
 * 线段树的区间成段更新
 * 延迟标记           *
 *********************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdlib>
#include <algorithm>

#define ls u << 1
#define rs u << 1 | 1
#define lson l, mid, u << 1
#define rson mid, r, u << 1 | 1
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
const int M = 8800;
int tmp[M << 2],a[M],to;

/*
 * 线段树的区间更新,需要注意此时的区间不再是点的更新,所以
 * 以[l,mid],[mid,r]来作为根的左右儿子,可以处理整段区间问题;
 */

struct Node {
    int u,v,c;
    void read() {
        scanf("%d %d %d",&u,&v,&c);
    }
} p[M];

struct Color{ //用来保存最后状态的区间染色情况;
    int l,r,c;
}color[M];

void pushdown(int u) {
    if(tmp[u] != -1) {
        tmp[ls] = tmp[rs] = tmp[u];
        tmp[u] = -1;
    }
}

void pushup(int u) {
    if(tmp[ls] == tmp[rs])
        tmp[u] = tmp[ls];
}

void update(int L,int R,int c,int l,int r,int u) {
    int mid = (l + r) >> 1;
    if(L <= l && R >= r) {
        tmp[u] = c;
    } else {
        pushdown(u);
        if(L < mid) update(L,R,c,lson);
        if(R > mid) update(L,R,c,rson);
        pushup(u);
    }
}

void query(int l,int r,int u) {
    int mid = (l + r) >> 1;
    if(tmp[u] != -1) {
        color[to].l = l;
        color[to].r = r;
        color[to++].c = tmp[u];
    } else {
        if(l == r - 1) return ;
        query(lson);
        query(rson);
    }
}

int main() {
    //freopen("in","r",stdin);
    int n;
    while(~scanf("%d",&n)) {
        memset(tmp,-1,sizeof(tmp));
        memset(a,0,sizeof(a));
        int L = M, R = -1,num = 0;
        for(int i = 0; i < n; i++) {
            p[i].read();
            L = min(L,p[i].u);
            R = max(R,p[i].v);
        }
        for(int i = 0; i < n; i++) {
            update(p[i].u,p[i].v,p[i].c,L,R,1);
        }
        to = 0;
        query(L,R,1);
        a[color[0].c]++;
        for(int i = 1; i < to; i++){
            if(color[i].l == color[i - 1].r && color[i].c == color[i - 1].c){
                //如果当前区间是衔接之间的区间且颜色又一致的话,则这两段区间同属一段;
                continue;
            }
            a[color[i].c]++; //否则为新的一段区间
        }
        for(int i = 0; i < M; i++){
            if(a[i]){
                printf("%d %d\n",i,a[i]);
            }
        }
        puts("");
    }
    return 0;
}
时间: 2025-01-01 09:40:50

Count the Colors(线段树之区间成段更新)的相关文章

POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 39795   Accepted: 11552 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ3468 A Simple Problem with Integers 【线段树】+【成段更新】

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 57666   Accepted: 17546 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

线段树入门之成段更新

作者:zifeiy 标签:线段树 HDU1698 Just a Hook 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 线段树功能: update:成段更新(因为query操作只涉及一次总区间,所以可以直接输出1节点的信息) #include <bits/stdc++.h> using namespace std; #define lson l, m, rt<<1 #define rson m+1, r, rt<<

HDU1698 Just a Hook 【线段树】+【成段更新】+【lazy标记】

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15889    Accepted Submission(s): 7897 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

[HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和.昨晚思前想后找有没有一个数学上的开平方的和等于和的开平方之类的规律.但是想了想发现这不就是小的时候,如果你这么想那老师就会骂死你的那个- -! 所以显然这个题是无法按套路成段更新了,懒惰标记也是没有用了,我们应该去按照区间更新每一个节点.结果TLE了一发,这说明这题不是这么搞,一定还有规律的.注意到题目给数据规模是2^63以及题目

树状数组成段更新——POJ 3468

A Simple Problem with IntegersCrawling in process... Crawling failed Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3468 Description You have N integers, A1, A2, ... , AN. You need to deal wit

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(线段树,区间覆盖,单点查询)

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