Time Limit: 3000 ms   Memory Limit: 256 MB

Description

  给你一个无限长的数组,初始的时候都为0,有3种操作:

  操作1是把给定区间$[l,r]$设为1,

  操作2是把给定区间$[l,r]$设为0,

  操作3把给定区间$[l,r]$0,1反转。

  一共n个操作,每次操作后要输出最小位置的0。

Input

  第一行一个整数n,表示有n个操作

  接下来n行,每行3个整数op,l,r表示一个操作

Output

  共n行,一行一个整数表示答案

Sample Input

Sample Output

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

HINT

  对于30%的数据$1\le n\le 10^3,1\le l\le r\le 10^{18}$

  对于100%的数据$1\le n\le 10^5,1\le l\le r\le 10^{18}$


题解

  离散化操作区间:

  首先看到$1\le l\le r\le 10^{18}$的范围,第一反应离散化。

    这题的离散化是非常讲究的,我们不能只把每个区间操作的两端点提取出来离散化(我就是这么干的,其他部分都是对的,结果眼睁睁地没法输出),因为这样无法考虑到区间之间的点,如下图:

  

  考虑到答案的位置,答案应该只可能出现在某一段操作区间右端点的右边一位,于是我们在离散一个操作区间$l,r$的同时,把$r+1$也离散化掉。操作并不涉及到$r+1$,仅仅是为了输出答案的正确和可行性。

  实现修改操作:

    看到熟悉的区间操作,当然要想想线段树啦。

     这里采用两棵线段树的写法实现3种操作,当然也有一棵线段树搞定的写法。

     两棵线段树$A,B$,都先按照离散化的规模建好,以离散化端点编号为索引。$A$记录$0$的信息,$B$记录$1$的信息。

     线段树维护的信息是:$0$或$1$最左出现的位置。

     第1个操作:将$A$的相应区间的信息清空(设置成最大值,因为不存在$0$了),将$B$的相应区间的信息填充(设置成区间的左端点位置),并打上清空或填充标记。日后记得下传。

     第2个操作:与第1个操作完全相反。

       第3个操作:将$A$的相应区间节点和$B$的相应区间节点对调。

  输出:

    询问$A$中的最小值位置,输出离散化前的原值即可。可以发现这个点一定是某个区间的$r$再$+1$。

  时间复杂度$O(n lg n)$,空间复杂度$O(n)$。


 #include <cstdio>
#include <algorithm>
#define min(a,b) (a<b?a:b)
using namespace std;
typedef long long ll;
const int N=1e5+;
ll INF=;
int n,lshtot,opt[N][],total;
ll inp[N][],lis[N*],minloc,maxloc,orival[N*];
void lshAndfill(){
sort(lis+,lis++lshtot);
total=unique(lis+,lis++lshtot)-lis-;
for(int i=;i<=total;i++) orival[i]=lis[i];
orival[total+]=INF;
for(int i=;i<=n;i++){
opt[i][]=inp[i][];
opt[i][]=lower_bound(lis+,lis++total,inp[i][])-lis;
opt[i][]=lower_bound(lis+,lis++total,inp[i][])-lis;
}
}
struct Seg{
int cnt,root[],sz,ch[N*][],mark[N*];
ll info[N*];
void build(int Size){
sz=Size;
_build(root[],,sz,true);
_build(root[],,sz,false);
}
void _build(int &u,int l,int r,bool isfill){
if(!u) u=++cnt;
mark[u]=-;
if(l==r){
if(isfill) info[u]=l;
else info[u]=total+;
return;
}
int mid=(l+r)>>;
_build(ch[u][],l,mid,isfill);
_build(ch[u][],mid+,r,isfill);
pushup(u);
}
inline void pushup(int u){
info[u]=min(info[ch[u][]],info[ch[u][]]);
}
inline void pushdown(int u,int l,int r){
int lc=ch[u][],rc=ch[u][];
if(mark[u]==-) return;
mark[lc]=mark[rc]=mark[u];
if(mark[u]==)
info[lc]=info[rc]=total+;
else{
info[lc]=l;
info[rc]=(l+r)/+;
}
mark[u]=-;
}
void setSeg(int flag,int l,int r){
_setSeg(root[^flag],root[^flag],,sz,l,r);
}
void _setSeg(int u1,int u2,int l,int r,int L,int R){
if(L<=l&&r<=R){
info[u1]=total+;
info[u2]=l;
mark[u1]=; mark[u2]=;
return;
}
pushdown(u1,l,r);
pushdown(u2,l,r);
int mid=(l+r)>>;
if(L<=mid) _setSeg(ch[u1][],ch[u2][],l,mid,L,R);
if(mid<R) _setSeg(ch[u1][],ch[u2][],mid+,r,L,R);
pushup(u1);
pushup(u2);
}
void swapSeg(int l,int r){_swapSeg(root[],root[],,sz,l,r);}
void _swapSeg(int &u1,int &u2,int l,int r,int L,int R){
if(L<=l&&r<=R){
swap(u1,u2);
return;
}
pushdown(u1,l,r);
pushdown(u2,l,r);
int mid=(l+r)>>;
if(L<=mid) _swapSeg(ch[u1][],ch[u2][],l,mid,L,R);
if(mid<R) _swapSeg(ch[u1][],ch[u2][],mid+,r,L,R);
pushup(u1);
pushup(u2);
}
inline ll getMin(int x){return info[root[x]];}
}seg;
int main(){
scanf("%d",&n);
minloc=-;
for(int i=;i<=n;i++){
scanf("%lld%lld%lld",&inp[i][],&inp[i][],&inp[i][]);
lis[++lshtot]=inp[i][];
lis[++lshtot]=inp[i][];
lis[++lshtot]=inp[i][]+;
if(minloc==-) minloc=min(inp[i][],inp[i][]);
else minloc=min(minloc,min(inp[i][],inp[i][]));
}
lshAndfill();
seg.build(total);
for(int i=;i<=n;i++){
if(minloc>){
printf("1\n");
continue;
}
if(opt[i][]<=)
seg.setSeg(opt[i][]==,opt[i][],opt[i][]);
else
seg.swapSeg(opt[i][],opt[i][]);
printf("%lld\n",orival[seg.getMin()]);
}
return ;
}

奇妙代码

mex (离散化+线段树)的更多相关文章

  1. 【XSY2484】mex 离散化 线段树

    题目大意 给你一个无限长的数组,初始的时候都为\(0\),有3种操作: 操作\(1\)是把给定区间\([l,r]\)设为\(1\): 操作\(2\)是把给定区间\([l,r]\)设为\(0\): 操作 ...

  2. 南阳理工 题目9:posters(离散化+线段树)

    posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6   描述 The citizens of Bytetown, AB, could not stand that ...

  3. SGU 180 Inversions(离散化 + 线段树求逆序对)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=180 解题报告:一个裸的求逆序对的题,离散化+线段树,也可以用离散化+树状数组.因为 ...

  4. 【POJ】2528 Mayor's posters ——离散化+线段树

    Mayor's posters Time Limit: 1000MS    Memory Limit: 65536K   Description The citizens of Bytetown, A ...

  5. hpu校赛--雪人的高度(离散化线段树)

    1721: 感恩节KK专场——雪人的高度 时间限制: 1 Sec  内存限制: 128 MB 提交: 81  解决: 35 [提交][状态][讨论版] 题目描述 大雪过后,KK决定在春秋大道的某些区间 ...

  6. 【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

    [BZOJ1645][Usaco2007 Open]City Horizon 城市地平线 Description Farmer John has taken his cows on a trip to ...

  7. 【bzoj4636】蒟蒻的数列 离散化+线段树

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801379.html 题目描述 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个 ...

  8. 离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

    题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前 ...

  9. Mayor's posters (离散化线段树+对lazy的理解)

    题目 题意: n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围 li,ri(1<=li<=ri<=10000000) .求出最后还能看见多少张海报. 思路: 由于 ...

  10. 干物妹小埋 (离散化 + 线段树 + DP)

    链接:https://ac.nowcoder.com/acm/contest/992/B来源:牛客网 题目描述 在之前很火的一个动漫<干物妹小埋>中,大家对小埋打游戏喝可乐的印象十分的深刻 ...

随机推荐

  1. Linux或Window是修改snmp的默认端口

    SNMP默认端口通讯使用 UDP 161,在安装一些监控软件的过程中,常常提示端口被占用等情况,下面说一下如何修改系统的默认SNMP端口 windows修改snmp端口 1 打开services文件 ...

  2. Python爬虫进阶(Scrapy框架爬虫)

    准备工作:           配置环境问题什么的我昨天已经写了,那么今天直接安装三个库                        首先第一步:                           ...

  3. CURL模拟post请求上传文件

    贴一段醍醐灌顶的话: 逻辑很简单,设置POST变量$post_data,其中upload指向需要发送的文件.这里要注意,我们之前使用POST都是发送一个字符串,然后在服务器端使用file_get_co ...

  4. LAMP_yum安装

    前言,人总是会越来越懒,说真的,我是摸着良心说话的 开始总是喜欢源码安装,因为可以定制,而且能显得有格调(逼格),但是一安装就要半天,还有各种依赖包的安装,各种报错,不忍直视 下面是我摘自晚上的一篇l ...

  5. css变量的用法——(--cssName)

    CSS变量,又称——CSS自定义属性,现在很多CSS预处理/后处理程序已作了相关快捷的编译处理, 基本用法有哪些呢,我们先看一个简单的栗子:——要求,创建一个五个块元素居中的分栏样式,奇数和偶数同高不 ...

  6. mui点击加载,下拉刷新,上下整合代码

    mui点击加载,下拉刷新,上下整合代码 mui的是上拉加载,但是老大说要做成点击加载,所以就改了一些 代码应该是有些问题的,测到了大家就自己改下. 首先要说明的是,有下拉刷新的页面一定要是双webvi ...

  7. Jmeter_打印当前时间戳&打印偏移时间戳

    Jmeter中提供了一种函数,可以打印时间戳,如下图 年: yyyy 月:MM 日:dd 时: HH 分: mm 秒:ss 关于时间戳的格式,可以自由组合定义,这里我写成这样 yyyy-MM-dd H ...

  8. Linux根据UUID自动挂载磁盘分区

    一般服务器都有多个硬盘分区,在重启后,这些分区的逻辑位置加载时可能会发生变动,如果使用传统的设备名称(例如:/dev/sda)方式挂载磁盘,就可能因为磁盘顺序变化而造成混乱. Linux环境中每个Bl ...

  9. VS2008集成PC-lint

    引言 C/C++语言的语法拥有其它语言所没有的灵活性,这种灵活性带来了代码效率的提升,但相应也使得代码编写具有很大的随意性,另外C/C++编译器不进行强制类型检查,也不做任何边界检查,这就增加了代码中 ...

  10. Django搭建博客网站(四)

    Django搭建博客网站(四) 最后一篇主要讲讲在后台文章编辑加入markdown,已经在文章详情页对markdown的解析. Django搭建博客网站(一) Django搭建博客网站(二) Djan ...