现在的位置: 首页 > 综合 > 正文

URAL – 1019 – Line Painting(离散化+线段树)

2019年08月29日 ⁄ 综合 ⁄ 共 1750字 ⁄ 字号 评论关闭

题意:在区间[0, 10^9]上染黑白两种颜色,问最后最长的白段的起点和终点。(初始区间全白)

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1019

——>>看数据可知要离散化。。而题意可知可用线段树去解决。。

对于区间[x, y],因为点到点,不是段到段,所以,可让x表示[x, x+1],整个区间的最后一点不表示,转化成段到段来解决。。于是[x, y]转化为[x, y-1]。。

时间复杂度为O(n)

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define lc (o<<1)
#define rc ((o<<1)|1)

const int maxn = 5000 + 10;

char cover[maxn<<3], color[maxn<<3];        //结点数已<<1,线段树结点再<<2,总<<3

int N, a[maxn], b[maxn], buf[maxn<<1], cnt;
char c[maxn];

void read() {
    cnt = 0;
    buf[++cnt] = 0;
    buf[++cnt] = 1000000000;
    for(int i = 1; i <= N; i++) {
        scanf("%d%d %c", a+i, b+i, c+i);
        buf[++cnt] = a[i];
        buf[++cnt] = b[i];
    }
}

void discretize() {
    sort(buf + 1, buf + 1 + cnt);
    cnt = unique(buf + 1, buf + 1 + cnt) - buf - 1;     //求个数要-1
}

void build(int o, int L, int R) {
    cover[o] = 0;
    if(L == R) return;
    int M = (L + R) >> 1;
    build(lc, L, M);
    build(rc, M + 1, R);
}

void pushdown(int o) {
    if(cover[o]) {
        cover[lc] = cover[rc] = cover[o];
        cover[o] = 0;
    }
}

void Insert(int o, int L, int R, int ql, int qr, char color) {
    if(ql <= L && R <= qr) {
        cover[o] = color;
        return;
    }
    pushdown(o);
    int M = (L + R) >> 1;
    if(ql <= M) Insert(lc, L, M, ql, qr, color);
    if(qr > M) Insert(rc, M+1, R, ql, qr, color);
}

void query(int o, int L, int R, int ql, int qr) {
    if(cover[o]) {      //我这个才正点!
        for(int i = L; i <= R; i++) color[i] = cover[o];
        return;
    }
    if(L == R) {
        color[L] = cover[o];
        if(color[L] == 0) color[L] = 'w';       //还是判一下
        return;
    }
    pushdown(o);
    int M = (L + R) >> 1;
    if(ql <= M) query(lc, L, M, ql, qr);
    if(qr > M) query(rc, M+1, R, ql, qr);
}

void solve() {
    for(int i = 1; i <= N; i++) {
        int A = lower_bound(buf + 1, buf + 1 + cnt, a[i]) - buf;
        int B = lower_bound(buf + 1, buf + 1 + cnt, b[i]) - buf;
        Insert(1, 1, cnt, A, B-1, c[i]);        //cnt个点,cnt-1段
    }
    query(1, 1, cnt, 1, cnt-1);     //只查cnt-1段
    int L = 0, R = 0, Max = 0;
    for(int i = 1; i < cnt; i++) {
        if(color[i] == 'w') {
            int l = i;
            while(i < cnt && color[i] == 'w') i++;
            int r = i;
            if(buf[r] - buf[l] > Max) {
                L = buf[l];
                R = buf[r];
                Max = R - L;
            }
        }
    }
    printf("%d %d\n", L, R);
}

int main()
{
    while(scanf("%d", &N) == 1) {
        read();
        discretize();
        build(1, 1, cnt);
        solve();
    }
    return 0;
}

抱歉!评论已关闭.