Codeforces 817F - MEX Queries

817F - MEX Queries

思路:

离线+离散化+线段树

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r

const int N=1e5+5;
int t[N],tree[N*16],lazy[N*16];
LL l[N],r[N];
vector<LL>vc;
void push_up(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void push_down(int rt,int l,int r){
    int m=(l+r)>>1;
    if(lazy[rt]==1){
        lazy[rt<<1]=lazy[rt<<1|1]=1;
        tree[rt<<1]=m-l+1;
        tree[rt<<1|1]=r-m;
    }
    else if(lazy[rt]==2){
        lazy[rt<<1]=lazy[rt<<1|1]=2;
        tree[rt<<1]=tree[rt<<1|1]=0;
    }
    else if(lazy[rt]==3){
        lazy[rt<<1]=3-lazy[rt<<1];
        lazy[rt<<1|1]=3-lazy[rt<<1|1];
        tree[rt<<1]=m-l+1-tree[rt<<1];
        tree[rt<<1|1]=r-m-tree[rt<<1|1];
    }
    lazy[rt]=0;
}
void build(int rt,int l,int r){
    if(l==r){
        tree[rt]=0;
        lazy[rt]=0;
        return ;
    }
    int m=(l+r)>>1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int t,int L,int R,int rt,int l,int r){
    if(L<=l&&r<=R){
        if(t==1){
            tree[rt]=r-l+1;
            lazy[rt]=1;
        }
        else if(t==2){
            tree[rt]=0;
            lazy[rt]=2;
        }
        else{
            if(lazy[rt]&&l!=r)push_down(rt,l,r);//注意这里,在更新第3种操作时,把之前在这个节点的操作pushdown
            tree[rt]=r-l+1-tree[rt];
            lazy[rt]=3;
        }
        return ;
    }
    if(lazy[rt])push_down(rt,l,r);
    int m=(l+r)>>1;
    if(L<=m)update(t,L,R,ls);
    if(R>m) update(t,L,R,rs);
    push_up(rt);
}
int query(int rt,int l,int r){
    if(l==r){
        return l;
    }
    if(lazy[rt])push_down(rt,l,r);
    int m=(l+r)>>1;
    if(tree[rt<<1]!=m-l+1)return query(ls);
    else return query(rs);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    vc.pb(1LL);
    for(int i=1;i<=n;i++)cin>>t[i]>>l[i]>>r[i],vc.pb(l[i]),vc.pb(r[i]),vc.pb(r[i]+1),vc.pb(l[i]+1);
    sort(vc.begin(),vc.end());
    vc.erase(unique(vc.begin(),vc.end()),vc.end());
    int m=vc.size();
    build(1,1,m);
    for(int i=1;i<=n;i++){
        int L=lower_bound(vc.begin(),vc.end(),l[i])-vc.begin()+1;
        int R=lower_bound(vc.begin(),vc.end(),r[i])-vc.begin()+1;
        update(t[i],L,R,1,1,m);
        cout<<vc[query(1,1,m)-1]<<endl;
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/widsom/p/8519724.html

时间: 2024-10-28 10:57:48

Codeforces 817F - MEX Queries的相关文章

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

codeforces 245H H. Queries for Number of Palindromes(区间dp)

题目链接: codeforces 245H 题目大意: 给出一个字符串,询问任意区间内的回文子串的个数. 题目分析: 定义isPar[i][j]表示区间字符串[i,j]是否是回文,可以通过isPar[i+1][j-1]递推得到. 定义dp[i][j]表示及区间[i,j]内的回文子串的个数,转移方程如下: dp[i][j]=dp[i+1][j]+dp[i][j?1]?dp[i+1][j?1]+isPar[i][j] 用到了一点容斥的思想. AC代码: #include <iostream> #i

CodeForces 932B Recursive Queries

Description Let us define two functions f and g on positive integer numbers. You need to process Q queries. In each query, you will be given three integers l, r and k. You need to print the number of integers xbetween l and r inclusive, such that g(x

「Codeforces」245H Queries for Number of Palindromes (区间dp)

题意:原题在这 You've got a string s = s1s2... s|s| of length |s|, consisting of lowercase English letters. There also are q queries, each query is described by two integers li, ri (1 ≤ li ≤ ri ≤ |s|). The answer to the query is the number of substrings of

CodeForces 825G&quot;Tree Queries&quot;(建树选根)

传送门 •参考资料 [1]:CodeForces 825G Educational Round #25 G :建树选根大法+O1大法+iostream解绑了还是慢 •题意 给定一颗包含 n 个节点的树,开始树的所有节点都是白色的: 给出 q 次询问,询问分为1.2两种: 将节点 x 涂成黑色. 询问节点 x 到所有的黑点节点的简单路径中的标号最小的那个点(包括起点和黑点) 题目保证第一次询问是 1 类型的. •题解 如果我们随便选取某节点作为根节点,那么询问的时候,我们要找到节点 x 到所有黑色

CodeForces 1294D MEX maximizing(思维)

http://codeforces.com/contest/1294/problem/D 大致题意: 刚开始有一个空集合,会往里添加q次数,每次加一个值,而且你可以让这个数任意加减x若干次 每次添加后就查询当前最小的不属于这个集合的非负整数是什么.尽可能让这个最小的不属于这个数列的非负整数最大. 解题思路: 由于每次添加的数t可以加减任意次的x,故我们只需记录t%x,用num[i]表示i的个数 用ans去递增查询是否可以满足要求就行,如果num[ans%x]不为0,说明之前有一个没发挥作用的t可

CF817F MEX Queries

题意 维护一个\(01\)串,一开始全部都是\(0\) \(3\)种操作 \(1.\)把一个区间都变为\(1\) \(2.\)把一个区间都变为\(0\) \(3.\)把一个区间的所有数字翻转过来 每次操作完成之后询问区间最小的\(0\)的位置 \(l,r<=10^{18}\) Sol 直接上线段树,如果这个区间左边是满的就去右边,否则去左边 动态开点,加上\(lazy\) 但这样会爆空间 所以把区间离散化 注意要离散\(1\),\(l\),\(r\),\(l+1\),\(r+1\) 这些都可能会

CF817F MEX Queries(线段树上二分)

题意 维护一个01串,一开始全部都是0 3种操作 1.把一个区间都变为1 2.把一个区间都变为0 3.把一个区间的所有数字翻转过来 每次操作完成之后询问区间最小的0的位置 l,r<=10^18 题解 区间操作想到线段树,离散化不用说,l,r太大了. 1,2,3操作非常好维护. 然后在查询中二分查询就好了. 一开始看别的博客(对,我看题解了,太菜)说要加1节点和r+1节点不知道为什么. 因为我的查询想的是,查询前面全都是1的区间的长度.后来发现做不了.就乖乖照题解做了. 1 #include<i

前缀和的应用 CodeForces - 932B Recursive Queries

题目链接: https://vjudge.net/problem/1377985/origin 题目大意就是要你把一个数字拆开,然后相乘. 要求得数要小于9,否则递归下去. 这里用到一个递归函数: int f(int x) { if(x < 10) return x; int ans = 1; while(x) { if(x%10 != 0) ans *= x%10; else ans *= 1; x /= 10; } return f(ans); } 这个函数用来求得一个数字最终得到的那个k值