码迷,mamicode.com
首页 > 其他好文 > 详细

CF817F MEX Queries

时间:2018-03-21 22:01:56      阅读:297      评论:0      收藏:0      [点我收藏+]

标签:答案   线段   oid   维护   位置   int   class   ons   线段树   

题意

维护一个\(01\)串,一开始全部都是\(0\)
\(3\)种操作
\(1.\)把一个区间都变为\(1\)
\(2.\)把一个区间都变为\(0\)
\(3.\)把一个区间的所有数字翻转过来
每次操作完成之后询问区间最小的\(0\)的位置
\(l,r<=10^{18}\)

Sol

直接上线段树,如果这个区间左边是满的就去右边,否则去左边
动态开点,加上\(lazy\)
但这样会爆空间

所以把区间离散化
注意要离散\(1\)\(l\)\(r\)\(l+1\)\(r+1\)
这些都可能会出现答案

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e5 + 5);

IL ll Input(){
    RG ll x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, len, opt[_];
ll ql[_], qr[_], o[_];
struct Segment{
    int sum, rev, tag;
} T[_ << 2];

IL void Adjust1(RG int x, RG int l, RG int r, RG int v){
    T[x].rev = 0, T[x].tag = v--;
    T[x].sum = v * (r - l + 1);
}

IL void Adjust2(RG int x, RG int l, RG int r){
    T[x].sum = r - l + 1 - T[x].sum;
    T[x].rev ^= 1;
}

IL void Pushdown(RG int x, RG int l, RG int r){
    RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
    if(T[x].tag){
        Adjust1(ls, l, mid, T[x].tag);
        Adjust1(rs, mid + 1, r, T[x].tag);
        T[x].tag = 0;
    }
    if(T[x].rev){
        Adjust2(ls, l, mid);
        Adjust2(rs, mid + 1, r);
        T[x].rev = 0;
    }
}

IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R, RG int v){
    if(L <= l && R >= r){
        Adjust1(x, l, r, v);
        return;
    }
    Pushdown(x, l, r);
    RG int mid = (l + r) >> 1;
    if(L <= mid) Modify(x << 1, l, mid, L, R, v);
    if(R > mid) Modify(x << 1 | 1, mid + 1, r, L, R, v);
    T[x].sum = T[x << 1].sum + T[x << 1 | 1].sum;
}

IL void Reverse(RG int x, RG int l, RG int r, RG int L, RG int R){
    if(L <= l && R >= r){
        Adjust2(x, l, r);
        return;
    }
    Pushdown(x, l, r);
    RG int mid = (l + r) >> 1;
    if(L <= mid) Reverse(x << 1, l, mid, L, R);
    if(R > mid) Reverse(x << 1 | 1, mid + 1, r, L, R);
    T[x].sum = T[x << 1].sum + T[x << 1 | 1].sum;
}

IL int Query(RG int x, RG int l, RG int r){
    if(l == r) return l;
    Pushdown(x, l, r);
    RG int mid = (l + r) >> 1, ans;
    if(T[x << 1].sum != mid - l + 1) ans = Query(x << 1, l, mid);
    else ans = Query(x << 1 | 1, mid + 1, r);
    T[x].sum = T[x << 1].sum + T[x << 1 | 1].sum;
    return ans;
}

int main(RG int argc, RG char *argv[]){
    n = Input(), o[++len] = 1;
    for(RG int i = 1; i <= n; ++i){
        opt[i] = Input(), ql[i] = Input(), qr[i] = Input();
        o[++len] = ql[i], o[++len] = qr[i];
        o[++len] = ql[i] + 1, o[++len] = qr[i] + 1;
    }
    sort(o + 1, o + len + 1), len = unique(o + 1, o + len + 1) - o - 1;
    for(RG int i = 1; i <= n; ++i){
        ql[i] = lower_bound(o + 1, o + len + 1, ql[i]) - o;
        qr[i] = lower_bound(o + 1, o + len + 1, qr[i]) - o;
        if(opt[i] == 1) Modify(1, 1, len, ql[i], qr[i], 2);
        else if(opt[i] == 2) Modify(1, 1, len, ql[i], qr[i], 1);
        else Reverse(1, 1, len, ql[i], qr[i]);
        printf("%lld\n", o[Query(1, 1, len)]);
    }
    return 0;
}

CF817F MEX Queries

标签:答案   线段   oid   维护   位置   int   class   ons   线段树   

原文地址:https://www.cnblogs.com/cjoieryl/p/8619821.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!