[Codeforces]817F. MEX Queries

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 l r — Add all missing numbers from the interval [l, r] 
2 l r — Remove all present numbers from the interval [l, r] 
3 l 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 ≤ 105). 
Next n lines contain three integer numbers t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 1018) — type of the query, left and right bounds. 
Output 
Print MEX of the set after each query. 
Examples 
input 

1 3 4 
3 1 6 
2 1 3 
output 



input 

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




Note 
Here are contents of the set after each query in the first example: 
{3, 4} — the interval [3, 4] is added 
{1, 2, 5, 6} — numbers {3, 4} from the interval [1, 6] got deleted and all the others are added 
{5, 6} — numbers {1, 2} got deleted

题意

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

题解

看到数据范围n<=10^5,结合题意可以考虑使用线段树维护对区间的修改操作。但是l,r<=10^18,所以首先要离散化一下。在使用线段树维护的时候,节点维护该区间数相加的总和。对于操作1和操作2,我们分别赋值为1和0,对于操作3,我们把区间反转,那么新的区间和就是区间的长度减去原来的区间和。然后每次查询最小位置的0,只需要看一下左儿子所代表的区间是否小于这个区间的长度,如果是就在左儿子,否则就在右儿子查找。

题目细节

这道题有很多坑人的点,首先,在离散化的时候必须把1也加上,因为答案可能为1;线段树在下传标记时要注意顺序;记录原来信息的数组必须得开long long,空间一定要开够。

代码

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(register int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=,p=;char ch=getchar();
while(!((''<=ch && ch<='') || ch=='-'))ch=getchar();
if(ch=='-')p=-,ch=getchar();
while(''<=ch && ch<='')sum=sum*+ch-,ch=getchar();
return sum*p;
}
const int maxn=; map <ll,int> mp;
int m,cnt;
ll s[maxn*],n; struct qu {
ll l,r;
int type;
}a[maxn]; struct node {
int s,lz,id;//s记录区间和,lz为懒标记,id维护区间是否反转
}c[maxn*]; #define lc (o<<1)
#define rc (o<<1 | 1)
#define left lc,l,mid
#define right rc,mid+1,r inline void make_tree(int o,int l,int r)
{
c[o].s=;c[o].lz=-;c[o].id=;
if(l==r)return;
int mid=(l+r)>>;
make_tree(left);
make_tree(right);
} void maintain(int o,int l,int r)
{
c[o].s=c[lc].s+c[rc].s;
} void pushdown(int o,int l,int r)
{
int mid=(l+r)>>;
if(c[o].lz!=-)//下传懒标记,同时将儿子节点的反转标记清0
{
c[lc].lz=c[rc].lz=c[o].lz;
c[lc].s=(mid-l+)*c[o].lz;
c[rc].s=(r-mid)*c[o].lz;
c[lc].id=c[rc].id=;
c[o].lz=-;
}
if(c[o].id)//将儿子节点的反转标记也反转,同时维护儿子的区间和
{
c[lc].id^=;
c[rc].id^=;
c[lc].s=(mid-l+)-c[lc].s;
c[rc].s=(r-mid)-c[rc].s;
c[o].id=;
}
} inline void updates(int ql,int qr,int x,int o,int l,int r)
{
pushdown(o,l,r);
if(ql==l && r==qr)//把区间覆盖为x
{
c[o].s=(r-l+)*x;
c[o].lz=x;
c[o].id=;
return;
}
int mid=(l+r)>>;
if(ql>mid)
{
updates(ql,qr,x,right);
}
else if(qr<=mid)
{
updates(ql,qr,x,left);
}else
{
updates(ql,mid,x,left);
updates(mid+,qr,x,right);
}
maintain(o,l,r);
} inline void updatex(int ql,int qr,int o,int l,int r)
{
pushdown(o,l,r);
if(ql==l && r==qr)//把区间反转
{
c[o].s=(r-l+)-c[o].s;
c[o].id^=;
return;
}
int mid=(l+r)>>;
if(ql>mid)
{
updatex(ql,qr,right);
}
else if(qr<=mid)
{
updatex(ql,qr,left);
}else
{
updatex(ql,mid,left);
updatex(mid+,qr,right);
}
maintain(o,l,r);
} void init()
{
m=read();
REP(i,,m)
{
cin>>a[i].type>>a[i].l>>a[i].r;
a[i].r++;
s[++cnt]=a[i].l;
s[++cnt]=a[i].r;
}
s[++cnt]=;//答案中可能会有1,必须加上
sort(s+,s+cnt+);
n=unique(s+,s+cnt+)-(s+);
REP(i,,n)mp[s[i]]=i;
make_tree(,,n);
} void query(int o,int l,int r)
{
if(l==r)
{
cout<<s[l]<<endl;
return;
}
int mid=(l+r)>>;
pushdown(o,l,r);
if(c[lc].s<mid-l+)
query(left);
else query(right);
} void doing()
{
REP(i,,m)
{
int type=a[i].type,l=mp[a[i].l],r=mp[a[i].r]-;
if(type==)
{
updates(l,r,,,,n);
}
else if(type==)
{
updates(l,r,,,,n);
}else
{
updatex(l,r,,,n);
}
query(,,n);
}
} int main()
{
init();
doing();
return ;
}

[Codeforces]817F. MEX Queries 离散化+线段树维护的更多相关文章

  1. Educational Codeforces Round 23 F. MEX Queries 离散化+线段树

    F. MEX Queries time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  2. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  3. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  4. Codeforces 817F MEX Queries

    题意:对一个维护三种操作:1.将[l..r]中的数全部加入集合中.2.将集合中[l..r]范围内的数删去.3.将集合中在[l..r]中的数删去,并将之前不在集合中的数加入集合 考虑到最近线段树总是写爆 ...

  5. mex (离散化+线段树)

    Time Limit: 3000 ms   Memory Limit: 256 MB Description 给你一个无限长的数组,初始的时候都为0,有3种操作: 操作1是把给定区间$[l,r]$设为 ...

  6. [Noi2016]区间[离散化+线段树维护+决策单调性]

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 621  Solved: 329[Submit][Status][D ...

  7. SPOJ - GSS1-Can you answer these queries I 线段树维护区间连续和最大值

    SPOJ - GSS1:https://vjudge.net/problem/SPOJ-GSS1 参考:http://www.cnblogs.com/shanyr/p/5710152.html?utm ...

  8. 2019牛客多校第七场E Find the median 离散化+线段树维护区间段

    Find the median 题意 刚开始集合为空,有n次操作,每次操作往集合里面插入[L[i],R[i]]的值,问每次操作后中位数是多少 分析 由于n比较大,并且数可以达到1e9,我们无法通过权值 ...

  9. Codeforces 997E - Good Subsegments(线段树维护最小值个数+历史最小值个数之和)

    Portal 题意: 给出排列 \(p_1,p_2,p_3,\dots,p_n\),定义一个区间 \([l,r]\) 是好的当且仅当 \(p_l,p_{l+1},p_{l+2},\dots,p_r\) ...

随机推荐

  1. VM安装Ubuntu问题合集(无法联网、中文界面设置、中文输入法etc)

    经常使用VM安装Ubuntu,安装系统的步骤跟着系统提示一步步下来就行,但总是遇到一些问题,这里记录一下常遇到的问题,以及自己解决的办法: 1.无法联网: 状况:Ubuntu不能联网,联网地方一直在闪 ...

  2. Android 基础:常用布局 介绍 & 使用(附 属性查询)

    Android 基础:常用布局 介绍 & 使用(附 属性查询)   前言 在 Android开发中,绘制UI时常需各种布局 今天,我将全面介绍Android开发中最常用的五大布局 含 Andr ...

  3. 使用logrotate分割tomcat日志

    转:https://www.52os.net/articles/using-logrotate-manage-tomcat-logs.html July 28, 2014 日志是Linux系统中最重要 ...

  4. Servlet--超链接,表单提交,重定向,转发4种情况的路径

    实际编码中我们经常写路径,写路径既可以写相对路径,也可以写绝对路径.我2年以前我就养成了习惯,只要是写路径我从来都是写绝对路径,因为万一将来我们的项目的目录发生变化,原来要是写相对路径的话就会有路径依 ...

  5. 【转】软件开发工具介绍之 6.Web开发工具

    [本文转自http://www.cnblogs.com/dusonchen/archive/2011/02/09/1739087.html ] 1.EditPlus 无论是编写xhtml页面,还是cs ...

  6. Android原生代码与html5交互

    一.首先是网页端,这个就是一些简单的标签语言和JS函数: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&q ...

  7. 02_HTML5+CSS3详解第五、六天(实战篇之HTML5制作企业网站)

    [废话连篇 - 实战篇,没什么好说的,最后一章兼容性问题懒得看了,over] Details 一.Xmind部分 xmind教程:http://www.jianshu.com/p/7c488d5e4b ...

  8. css盒子居中定位问题

    在HTML中,div盒子的居中要通过外边距margin和width来控制,首先确定盒子的宽度,然后确定盒子方位并将其平移便可使盒子移到固定位置. <div id="divpic&quo ...

  9. linux下^M问题

    ^M的原因 Dos.Windows 格式的文件,用 0D 0A (CR+LF)作为换行符 而Unix 的则是以0A(LF) 作为换行符 所以dos 底下的文本文件到了unix的话,换行符就会多出来一个 ...

  10. awk脚本使用的几种方法

    1. awk名包含在文件内 [root@nhserver1 08]# cat sample.txtaaabbbccc [root@nhserver1 08]# cat readsample.awkaw ...