zoukankan      html  css  js  c++  java
  • codeforces CF817F MEX Queries 线段树 离散化

    $ Rightarrow $ 戳我进CF原题

    F. MEX Queries


    time limit per test: 2 seconds
    memory limit per test: 256 megabytes
    input: standard input
    output: standard output

     

    You are given a set of integer numbers, initially it is empty. You should perform $ n $ queries.
    There are three different types of queries:
     

    • $ 1 quad l quad r $ — Add all missing numbers from the interval $ [l, r] $
    • $ 2 quad l quad r $ — Remove all present numbers from the interval $ [l, r] $
    • $ 3 quad l quad r $ — Invert the interval $ [l, r] $ — add all missing and remove all present numbers from the interval $ [l, r] $
       

    After each query you should output $ MEX $ of the set
    — the smallest positive $ (MEX  ≥ 1) $ integer number which is not presented in the set.
     

    Input

    The first line contains one integer number $ n (1 ≤ n ≤ 10^5) $ .
    Next $ n $ lines contain three integer numbers $ t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 10^18) $ — type of the query, left and right bounds.
     

    Output

    Print $ MEX $ of the set after each query.
     

    Examples

    input1

     3
     1 3 4
     3 1 6
     2 1 3
    

    output1

     1 
     3
     1
    

    input2

     4
     1 1 3
     3 5 6
     2 4 4
     3 1 6
    

    output2

     4
     4
     4
     1
    

     

    Note

    Here are contents of the set after each query in the first example:

    1. $ (3, 4) $ — the interval $ [3, 4] $ is added
    2. $ (1, 2, 5, 6) $ — numbers $ (3, 4) $ from the interval $ [1, 6] $ got deleted and all the others are added
    3. $ (5, 6) $ — numbers $ (1, 2) $ got deleted
       

    题目大意

    • 给你一个无限长的数组,初始的时候都为 $ 0 $ ,
      操作 $ 1 $ 是把给定区间设为 $ 1 $ ,
      操作 $ 2 $ 是把给定区间清零,
      操作 $ 3 $ 是把给定区间反转。
      每次操作后要输出最小位置的 $ 0 $ 。

    • 数据范围:$ 1 le n le 10^5 $
       

    思路

    • 线段树+离散化

    • 操作 $ 1 $ 和 $ 2 $ :区间赋值

    • 操作 $ 3 $ :相当于区间每个数 $ xor quad 1 $

    • 可以维护线段树的区间长度,线段树上二分即可

    • 注意:

    1. 求的是 $ mex $ ,可能不是 $ l_i,r_i $ 中的任何一个,对于 $ 1,l_{i+1},r_{i+1} $ 也要离散。
    2. 记录原来信息的数组必须得开 $ long quad long $
       

    代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define ll long long
    #define N 400005
    inline ll read() {
        register char ch;
        while(!isdigit(ch=getchar()));
        register ll x=ch^'0';
        while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
        return x;
    }
    int n,m,opt[N];
    ll a[N<<2],ql[N],qr[N],sum[N<<2],lzy[N<<2],rev[N<<2];
    inline void pushdown(int o,int l,int r){
    	int mid=l+r>>1;
    	if(lzy[o]){
    		lzy[o<<1]=lzy[o<<1|1]=lzy[o]--;
    		sum[o<<1]=(mid-l+1)*lzy[o];
    		sum[o<<1|1]=(r-mid)*lzy[o];
    		lzy[o]=rev[o<<1]=rev[o<<1|1]=0;
    	}
    	if(rev[o]){
    		sum[o<<1]=mid-l+1-sum[o<<1];
    		sum[o<<1|1]=r-mid-sum[o<<1|1];
    		rev[o<<1]^=1;
    		rev[o<<1|1]^=1;
    		rev[o]=0;
    	}
    }
    void updata(int o,int l,int r,int L,int R,int val){
    	if(L<=l&&r<=R){
    		lzy[o]=val--; rev[o]=0;
    		sum[o]=(val)*(r-l+1);
    		return;
    	}
    	pushdown(o,l,r);
    	int mid=l+r>>1;
    	if(L>mid) updata(o<<1|1,mid+1,r,L,R,val);
    	else if(R<=mid) updata(o<<1,l,mid,L,R,val);
    	else{
    		updata(o<<1,l,mid,L,R,val);
    		updata(o<<1|1,mid+1,r,L,R,val);
    	}
    	sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    void modify(int o,int l,int r,int L,int R){
    	if(L<=l&&r<=R){
    		sum[o]=r-l+1-sum[o];
    		rev[o]^=1;
    		return;
    	}
    	pushdown(o,l,r);
    	int mid=l+r>>1;
    	if(L>mid) modify(o<<1|1,mid+1,r,L,R);
    	else if(R<=mid) modify(o<<1,l,mid,L,R);
    	else{
    		modify(o<<1,l,mid,L,R);
    		modify(o<<1|1,mid+1,r,L,R);
    	}
    	sum[o]=sum[o<<1]+sum[o<<1|1];	
    }
    ll query(int o,int l,int r){
    	if(l==r) return a[l];
    	pushdown(o,l,r);
    	int mid=l+r>>1;
    	ll res;
    	if(sum[o<<1]!=mid-l+1) res=query(o<<1,l,mid);
    	else res=query(o<<1|1,mid+1,r);
    	sum[o]=sum[o<<1]+sum[o<<1|1];
    	return res;
    }
    signed main(){
    	n=read(); a[++m]=1;
    	for(int i=1;i<=n;++i){
    		opt[i]=read(); ql[i]=read(); qr[i]=read();
    		a[++m]=ql[i]; a[++m]=ql[i]+1;
    		a[++m]=qr[i]; a[++m]=qr[i]+1;
    	}
    	sort(a+1,a+1+m);
    	m=unique(a+1,a+1+m)-(a+1);
    	for(int i=1;i<=n;++i){
    		int L=lower_bound(a+1,a+1+m,ql[i])-a;
    		int R=lower_bound(a+1,a+1+m,qr[i])-a;
    		if(opt[i]==1||opt[i]==2) updata(1,1,m,L,R,opt[i]==1 ? 2 : 1);
    		else modify(1,1,m,L,R);
    		printf("%lld
    ",query(1,1,m));
    	}
    	return 0;
    }
    /*
    #        42702002
    When     2018-09-09 14:03:14 
    Who      PotremZ 
    Problem  F - MEX Queries 
    Lang     GNU C++11
    Verdict  Accepted 
    Time     264 ms 
    Memory   57900 KB 
    */
    
  • 相关阅读:
    VS操作Sqlite数据库
    Sqlite官方下载对应版本注意细节
    样式
    移动端问题
    table最终版IE(浏览器中宽度不起作用)
    pointer-event:none;在IE浏览器中不起作用
    伪类的使用
    针对谷歌浏览器写的css样式
    IE浏览器中textarea有滚动条出现
    父级元素被子元素的margin-top值影响的解决方案
  • 原文地址:https://www.cnblogs.com/PotremZ/p/CF817F.html
Copyright © 2011-2022 走看看