cf545(线段树 + 离散化)

简介: cf545(线段树 + 离散化)

维护一个01串,一开始全部都是0


3种操作


1.把一个区间都变为1


2.把一个区间都变为0


3.把一个区间的所有数字翻转过来


每次操作完成之后询问区间最小的0的位置


l,r<=10^18


思路:先离散化(注意一定要把1也离散进去) 然后对每个区间[l,r] 把l-1,r+1也离散进去,最后维护一颗线段树(维护最大值和最小值)

#include <bits/stdc++.h>
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int maxn = 5e6 + 5;
typedef long long ll;
struct Tree {
    int l, r;
    int mm, mx, lazy;
}tree[maxn];
ll Hash[maxn], len;
void pushup(int i) {
    tree[i].mx = max(tree[lson].mx, tree[rson].mx);
    tree[i].mm = min(tree[lson].mm, tree[rson].mm);
}
void check(int i) {
    if (tree[i].mx == 0) {
        tree[i].mm = tree[i].mx = 1;
    } else if (tree[i].mm == 1) {
        tree[i].mm = tree[i].mx = 0;
    }
}
void pushdown(int i) {
    if (tree[i].lazy == 0) return ;
    if (tree[i].lazy == 1) {
        tree[lson].mm = tree[lson].mx = 1;
        tree[rson].mm = tree[rson].mx = 1;
        tree[lson].lazy = 1; tree[rson].lazy = 1;
    } else if (tree[i].lazy == 2) {
        tree[lson].mm = tree[lson].mx = 0;
        tree[rson].mm = tree[rson].mx = 0;
        tree[lson].lazy = 2; tree[rson].lazy = 2;
    } else if (tree[i].lazy == 3) {
        if (tree[lson].lazy == 3) {
            check(lson); tree[lson].lazy = 0;
        } else if (tree[lson].lazy == 1) {
            check(lson); tree[lson].lazy = 2;
        } else if (tree[lson].lazy == 2) {
            check(lson); tree[lson].lazy = 1;
        } else if (tree[lson].lazy == 0) {
            check(lson); tree[lson].lazy = 3;
        }
        if (tree[rson].lazy == 3) {
            check(rson); tree[rson].lazy = 0;
        } else if (tree[rson].lazy == 1) {
            check(rson); tree[rson].lazy = 2;
        } else if (tree[rson].lazy == 2) {
            check(rson); tree[rson].lazy = 1;
        } else if (tree[rson].lazy == 0) {
            check(rson); tree[rson].lazy = 3;
        }
    }
    tree[i].lazy = 0;
}
void build(int i, int l, int r) {
    tree[i].l = l;
    tree[i].r = r;
    if (l >= r) return ;
    int mid = (l + r) / 2;
    build(lson, l, mid);
    build(rson, mid + 1, r);
    pushup(i);
}
struct node {
    ll opt, l, r;
}q[maxn];
void updata(int i, int l, int r, int opt) {
    pushdown(i);
    int x = tree[i].l, y = tree[i].r;
    if (tree[i].l == l && tree[i].r == r) {
        if (opt == 1) {
            tree[i].mm = tree[i].mx = tree[i].lazy = 1;
        } else if (opt == 2) {
            tree[i].mm = tree[i].mx = 0; tree[i].lazy = 2;
        } else if (opt == 3) {
            if (tree[i].mx == 0) {
                tree[i].mm = tree[i].mx = 1;
            } else if (tree[i].mm == 1) {
                tree[i].mm = tree[i].mx = 0;
            }
            tree[i].lazy = 3;
        }
        return ;
    }
    int mid = (tree[i].l + tree[i].r) / 2;
    if (mid >= r) {
        updata(lson, l, r, opt);
    } else if (l > mid) {
        updata(rson, l, r, opt);
    } else {
        updata(lson, l, mid, opt);
        updata(rson, mid + 1, r, opt);
    }
    pushup(i);
}
ll query(int i) {
    pushdown(i);
    if (tree[i].l == tree[i].r) {
        return tree[i].l;
    }
    int mid = (tree[i].l + tree[i].r) / 2;
    if (tree[i * 2].mm == 0) {
        return query(lson);
    } else {
        return query(rson);
    }
}
/**/
int main() {
    int n;
    scanf("%d", &n);
    Hash[++len] = 1;
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld%lld", &q[i].opt, &q[i].l, &q[i].r);
        Hash[++len] = q[i].l; Hash[++len] = max(q[i].l - 1, 1LL);
        Hash[++len] = q[i].r; Hash[++len] = q[i].r + 1;
    }
    sort (Hash + 1, Hash + len + 1);
    len = unique(Hash + 1, Hash + len + 1) - Hash - 1;
    build(1, 1, len);
    for (int i = 1; i <= n; i++) {
        q[i].l = lower_bound(Hash + 1, Hash + len + 1, q[i].l) - Hash;
        q[i].r = lower_bound(Hash + 1, Hash + len + 1, q[i].r) - Hash;
        updata(1, q[i].l, q[i].r, q[i].opt);
        printf("%lld\n", Hash[query(1)]);
    }
    return 0;
}
相关文章
|
8月前
|
算法 C语言
分治法——找众数
分治法——找众数
|
8月前
|
机器学习/深度学习 算法 测试技术
【动态规划】C++算法:446等差数列划分 II - 子序列
【动态规划】C++算法:446等差数列划分 II - 子序列
|
存储 算法 C++
C++基础算法离散化及区间合并篇
C++基础算法离散化及区间合并篇
175 0
|
8月前
【数值分析】二分法求方程的根(附matlab代码)
【数值分析】二分法求方程的根(附matlab代码)
|
8月前
|
算法 测试技术 C#
【动态规划】【前缀和】【和式变换】100216. K 个不相交子数组的最大能量值
【动态规划】【前缀和】【和式变换】100216. K 个不相交子数组的最大能量值
|
5月前
|
算法 索引
【算法】二分算法——山脉数组的峰顶索引
【算法】二分算法——山脉数组的峰顶索引
|
8月前
|
存储 机器学习/深度学习 人工智能
【算法基础】基础算法(三)--(双指针算法、位运算、离散化、区间合并)
【算法基础】基础算法(三)--(双指针算法、位运算、离散化、区间合并)
|
人工智能 算法
动态规划之区间一维
噩梦中的仙境:动态规划之区间一维
83 0
动态规划之区间一维
|
算法 关系型数据库 MySQL
前缀和和差分和dijkstra算法和二分算法和floyd算法
前缀和和差分和dijkstra算法和二分算法和floyd算法
【14. 区间和(离散化)】
离散化 - 假设一共有10&lt;sup&gt;5&lt;/sup&gt;个数,每个数的值域是0~10&lt;sup&gt;9&lt;/sup&gt;,有些题目可能会使用这些值下标来做,但是我们如果开一个长度是10&lt;sup&gt;9&lt;/sup&gt;数组是不现实的。这时候就需要用到`映射`。 - 我们需要把这个序列映射到从1开始的`连续自然数`,这个过程就叫离散化。
125 0
【14. 区间和(离散化)】