ural 1019 Line Painting(线段树)

题目链接:ural 1019 Line Painting

题目大意:一个0~1e9的区间,初始都是白的,现进行N次操作,每次将一段区间图上一中颜色。最后问说连续最长的白色区间。

解题思路:线段树区间合并,每个节点即维护一个区间,很经典。注意坐标需要离散化,但是还是要将0和1e9放进去。

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

using namespace std;

const int maxn = 10005;
const int INF = 0x3f3f3f3f;

#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
struct pii {
    int len, pos;
    pii (int len = 0, int pos = 0) {
        this->len = len;
        this->pos = pos;
    }
    friend bool operator < (const pii& a, const pii& b) {
        if (a.len != b.len)
            return a.len < b.len;
        return a.pos > b.pos;
    }
}s[maxn << 2];
int N, M, pos[maxn], cnt = 0;
int lc[maxn << 2], rc[maxn << 2], L[maxn << 2], R[maxn << 2], set[maxn << 2];

inline int length(int u) {
    return pos[rc[u] + 1] - pos[lc[u]];
}

inline void maintain(int u, int w) {
    set[u] = w;
    if (w) {
        L[u] = R[u] = length(u);
        s[u] = pii(R[u], pos[lc[u]]);
    } else {
        L[u] = R[u] = 0;
        s[u] = pii(0, INF);
    }
}

inline void pushup(int u) {
    pii cur (L[rson(u)] + R[lson(u)], pos[lc[rson(u)]] - R[lson(u)]);
    s[u] = max(max(s[lson(u)], s[rson(u)]), cur);
    L[u] = L[lson(u)] + (L[lson(u)] == length(lson(u)) ? L[rson(u)] : 0);
    R[u] = R[rson(u)] + (R[rson(u)] == length(rson(u)) ? R[lson(u)] : 0);
    //printf("%d %d:%d %d!\n", lc[u], rc[u], s[u].pos, s[u].pos + s[u].len);
}

inline void pushdown(int u) {
    if (set[u] != -1) {
        maintain(lson(u), set[u]);
        maintain(rson(u), set[u]);
        set[u] = -1;
    }
}

void build(int u, int l, int r) {
    lc[u] = l; rc[u] = r;
    set[u] = -1;

    if (l == r) {
        L[u] = R[u] = length(u);
        s[u] = pii(R[u], pos[lc[u]]);
        return;
    }
    int mid = (lc[u] + rc[u]) >> 1;
    build(lson(u), l, mid);
    build(rson(u), mid+1, r);
    pushup(u);
}

void modify(int u, int l, int r, int w) {
    if (l <= lc[u] && rc[u] <= r) {
        maintain(u, w);
        return;
    }

    pushdown(u);
    int mid = (lc[u] + rc[u]) >> 1;
    if (l <= mid)
        modify(lson(u), l, r, w);
    if (r > mid)
        modify(rson(u), l, r, w);
    pushup(u);
}

pii query(int u, int l, int r) {
    if (l <= lc[u] && rc[u] <= r)
        return s[u];
    pushdown(u);
    int mid = (lc[u] + rc[u]) >> 1;
    pii ret(0, INF);
    if (l <= mid)
        ret = max(ret, query(lson(u), l, r));
    if (r > mid)
        ret = max(ret, query(rson(u), l, r));
    pushup(u);
    return ret;
}

struct Seg {
    int l, r;
    char op[5];
    void read() { scanf("%d%d%s", &l, &r, op);}
}q[maxn];

int find (int x) {
    return lower_bound(pos, pos + M, x) - pos;
}

void init () {
    int n = 0;
    for (int i = 1; i <= N; i++) {
        q[i].read();
        pos[i*2-1] = q[i].l;
        pos[i*2] = q[i].r;
    }

    sort(pos + 1, pos + 1 + N * 2);
    M = unique(pos + 1, pos + 1 + N * 2) - (pos+1);
    pos[0] = 0;
    pos[M + 1] = 1e9;
    build(1, 0, M);
}

int main () {
    while (scanf("%d", &N) == 1) {
        init();

        for (int i = 1; i <= N; i++) {
            modify(1, find(q[i].l), find(q[i].r)-1, q[i].op[0] == ‘w‘ ? 1 : 0);
        }
        printf("%d %d\n", s[1].pos, s[1].pos + s[1].len);
    }
    return 0;
}
时间: 2024-10-06 20:20:21

ural 1019 Line Painting(线段树)的相关文章

URAL 1019. Line Painting 线段树 区间合并 离散化

题目来源:URAL 1019. Line Painting 题意:求最长的一段全部为白色的区间 思路:线段树成段更新 区间合并 离散化 这里对应的是一段区间 所以每次不是m+1 而是 l m 和 m r 了 另外我加上了0 和 10^9 这两个点 每一段区间(l, r)我记录的是l和r之间有多少条线段 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const

51Nod 1019 逆序数(线段树)

题目链接:逆序数 模板题. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 #define lson i << 1, L, mid 7 #define rson i << 1 | 1, mid + 1, R 8 9 const int N = 100010; 10 11 long long ans

线段树详解 (原理,实现与应用)

线段树详解 By 岩之痕 目录: 一:综述 二:原理 三:递归实现 四:非递归原理 五:非递归实现 六:线段树解题模型 七:扫描线 八:可持久化 (主席树) 九:练习题 一:综述 假设有编号从1到n的n个点,每个点都存了一些信息,用[L,R]表示下标从L到R的这些点. 线段树的用处就是,对编号连续的一些点进行修改或者统计操作,修改和统计的复杂度都是O(log2(n)). 线段树的原理,就是,将[1,n]分解成若干特定的子区间(数量不超过4*n),然后,将每个区间[L,R]都分解为 少量特定的子区

URAL 1989 Subpalindromes(回文串 线段树 多项式hash)

1989. Subpalindromes Time limit: 0.5 second Memory limit: 64 MB You have a string and queries of two types: replace i'th character of the string by character a; check if substring sj...sk is a palindrome. Input The first line contains a string consis

ural 1707. Hypnotoad&#39;s Secret(线段树)

题目链接:ural 1707. Hypnotoad's Secret 题目大意:给定N和M,然后N组s0, t0, Δs, Δt, k,每组可以计算出k个星星的坐标:M组a0, b0, c0, d0, Δa, Δb, Δc, Δd, q,每组要求算出q个矩形,判断矩形内是否包含星星,对于q≥20的情况要根据公式计算一个值即可. 解题思路:计算出所有的星星坐标和矩阵,这个每的说了,将矩阵差分成两点,通过计算出每个点左下角有多少个星 星,然后用容斥计算出矩阵内是否有点.这个属于线段树的一个应用. #

URAL 2014 Zhenya moves from parents 线段树

线段树,前缀和最小 Zhenya moves from parents Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description Zhenya moved from his parents' home to study in other city. He didn't take any cash with him, he only took his f

URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)

题目链接: URAL 1890 . Money out of Thin Air 题目描述: 给出一个公司里面上司和下级的附属关系,还有每一个人的工资,然后有两种询问: 1:employee x y z ,如果编号为x的员工如果工资小于y,就给他加薪z. 2:department x y z ,如果编号为x的员工所管辖的范围内(包括自己),所有员工的工资平均数小于y,给该范围加薪z. 问q次操作后这个公司内每个员工的工资为多少? 解题思路: 根据上司和下级的附属关系,可以先建一个有向图,然后对有向

Codeforces 484E. Sign on Fence 可持久化线段树

大概题意: 给一数组a,问在某一区间L~R中,问对于连续的长为W的一段中最小的数字的最大值是多少. 显然可以转化成二分高度然后判断可行性的问题. 考虑到高度肯定为数组中的某一个值,将数组从大到小排序. 建n棵线段树,对于第 i 棵线段树,将 大于等于a[i] 的叶子的值设置为1,其他的叶子设置为0,问题就转化成了用线段树求某一区间中最长的连续的1的个数,这是一个线段树的经典问题,可以通过维护每个节点的 左边连续和,右边连续和,连续和的最大值 得到. 由于空间问题,不可能建立10^5棵线段树,考虑

HDU 5023 A Corrupt Mayor&#39;s Performance Art (线段树)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 255    Accepted Submission(s): 114 Problem Description Corrupt governors always find ways to get dirty money.