很久以前写过二分答案离线的做法,比较好理解。事实上这还是一个线段树合并+分裂的板子题,相比离线做法以更优的复杂度做了更多的事情。具体不说了。怎么交了一遍luogu上就跑第一了啊

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
#define N 100010
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,root[N],rev[N],cnt;
struct data{int l,r,x;
}tree[N<<];
struct data2
{
int l,r;
bool operator <(const data2&a) const
{
return r<a.r;
}
};
set<data2> q;
void ins(int &k,int x,int l,int r)
{
if (!k) k=++cnt;tree[k].x++;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,x,l,mid);
else ins(tree[k].r,x,mid+,r);
}
void split(int &x,int &y,int rk,int op)
{
if (!x) return;
tree[y=++cnt].x=tree[x].x-rk,tree[x].x=rk;
if (op==)
{
if (tree[tree[x].l].x==rk)
{
tree[y].r=tree[x].r,tree[x].r=;
return;
}
else if (tree[tree[x].l].x>rk)
{
tree[y].r=tree[x].r,tree[x].r=;
split(tree[x].l,tree[y].l,rk,op);
}
else split(tree[x].r,tree[y].r,rk-tree[tree[x].l].x,op);
}
else
{
if (tree[tree[x].r].x==rk)
{
tree[y].l=tree[x].l,tree[x].l=;
return;
}
else if (tree[tree[x].r].x>rk)
{
tree[y].l=tree[x].l,tree[x].l=;
split(tree[x].r,tree[y].r,rk,op);
}
else split(tree[x].l,tree[y].l,rk-tree[tree[x].r].x,op);
}
}
void merge(int &x,int &y,int l,int r)
{
if (!x||!y) {x|=y;return;}
tree[x].x+=tree[y].x;
if (l<r)
{
int mid=l+r>>;
merge(tree[x].l,tree[y].l,l,mid);
merge(tree[x].r,tree[y].r,mid+,r);
}
}
int query(int k,int l,int r,int x,int op)
{
if (l==r) return l;
int mid=l+r>>;
if (op==)
{
if (tree[tree[k].l].x>=x) return query(tree[k].l,l,mid,x,op);
else return query(tree[k].r,mid+,r,x-tree[tree[k].l].x,op);
}
else
{
if (tree[tree[k].r].x>=x) return query(tree[k].r,mid+,r,x,op);
else return query(tree[k].l,l,mid,x-tree[tree[k].r].x,op);
}
}
void print(int k,int l,int r)
{
if (!tree[k].x) return;
if (l==r) {cout<<l<<' ';return;}
int mid=l+r>>;
print(tree[k].l,l,mid),print(tree[k].r,mid+,r);
}
int main()
{
n=read(),m=read();
for (int i=;i<=n;i++) ins(root[i],read(),,n),q.insert((data2){i,i});
while (m--)
{
int op=read(),l=read(),r=read();
set<data2>::iterator it=q.lower_bound((data2){l,l});
if ((*it).l<l)
{
split(root[(*it).l],root[l],l-(*it).l,rev[(*it).l]);
int L=(*it).l,R=(*it).r;
q.erase(it);
q.insert((data2){L,l-});
q.insert((data2){l,R});
rev[l]=rev[L];
}
it=q.lower_bound((data2){r+,r+});
if (it!=q.end()&&(*it).l<=r)
{
split(root[(*it).l],root[r+],r-(*it).l+,rev[(*it).l]);
int L=(*it).l,R=(*it).r;
q.erase(it);
q.insert((data2){L,r});
q.insert((data2){r+,R});
rev[r+]=rev[L];
}
it=q.lower_bound((data2){l,l});it++;
while (it!=q.end()&&(*it).r<=r) merge(root[l],root[(*it).l],,n),it++;
it=q.lower_bound((data2){l,l});
while (it!=q.end()&&(*it).r<=r) q.erase(it),it=q.lower_bound((data2){l,l});
q.insert((data2){l,r});
rev[l]=op;
//it=q.begin();while (it!=q.end()) cout<<(*it).l<<' '<<(*it).r<<" ",print(root[(*it).l],1,n),it++,cout<<endl;cout<<endl;
//it=q.begin();while (it!=q.end()) cout<<(*it).l<<' '<<(*it).r<<endl,it++;cout<<endl;
}
int x=read();
set<data2>::iterator it=q.lower_bound((data2){x,x});
cout<<query(root[(*it).l],,n,x-(*it).l+,rev[(*it).l]);
/*for (int x=1;x<=n;x++)
{
set<data2>::iterator it=q.lower_bound((data2){x,x});
cout<<query(root[(*it).l],1,n,x-(*it).l+1,rev[(*it).l])<<' ';
}*/
}

BZOJ4552 HEOI2016/TJOI2016排序(线段树合并+线段树分裂)的更多相关文章

  1. [HEOI2016/TJOI2016]排序 线段树+二分

    [HEOI2016/TJOI2016]排序 内存限制:256 MiB 时间限制:6000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而 ...

  2. [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)

    题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...

  3. 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)

    2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...

  4. 2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)

    2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点 ...

  5. 洛谷 P2824 [HEOI2016/TJOI2016]排序 解题报告

    P2824 [HEOI2016/TJOI2016]排序 题意: 有一个长度为\(n\)的1-n的排列\(m\)次操作 \((0,l,r)\)表示序列从\(l\)到\(r\)降序 \((1,l,r)\) ...

  6. 【线段树合并】【P2824】 [HEOI2016/TJOI2016]排序

    Description 给定一个长度为 \(n\) 的排列,有 \(m\) 次操作,每次选取一段局部进行升序或降序排序,问你一波操作后某个位置上的数字是几 Hint \(1~\leq~n,~m~\le ...

  7. 洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)

    (另外:题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法) 线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details ...

  8. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  9. HDU 5649 DZY Loves Sorting(二分答案+线段树/线段树合并+线段树分割)

    题意 一个 \(1\) 到 \(n\) 的全排列,\(m\) 种操作,每次将一段区间 \([l,r]\) 按升序或降序排列,求 \(m\) 次操作后的第 \(k\) 位. \(1 \leq n \le ...

随机推荐

  1. Mac 系统占用100g的解决办法

    Mac 关于本机-磁盘管理,如果发现系统占用超过80g以上的小伙伴们可以做以下操作只需要以下4个步骤,轻松降到30g以内!!!!!!!(仅适用于安装了Xcode的小伙伴) 打开Finder,comma ...

  2. AndroidTV端的requestFocus()问题

    每次开机盒子或者电视的时候,发现给某些控件设置请求焦点 requestFocus 会失效 最终的解决办法就是延时请求 view.postDelayed(new Runnable() { @Overri ...

  3. Cygwin 编译 ffmpeg

    1.在官网下载linux下的压缩包 https://ffmpeg.zeranoe.com/builds/source/ffmpeg/ffmpeg-3.2.4.tar.xz 2.进入cygwin,假定将 ...

  4. selenium-获取元素属性(六)

    获取元素属性很简单,使用 get_attribute 方法即可 如下图 获取具体的属性直接将该属性名当作参数传入即可 若是获取值,则获取的实则是该元素的 value,需要将 value 当参数传入 i ...

  5. Python 日志模块logging

    logging模块: logging是一个日志记录模块,可以记录我们日常的操作. logging日志文件写入默认是gbk编码格式的,所以在查看时需要使用gbk的解码方式打开. logging日志等级: ...

  6. STP生成树协议

    STP主要作用 1.消除环路:通过阻断冗余链路来消除网络中可能存在的链路 2.链路备份:当活动那个路径发生故障时,激活备份链路,及时恢复网络连通性. 根桥选举 每个交换机启动STP后,都认为自己是根桥 ...

  7. LeetCode算法题-License Key Formatting(Java实现)

    这是悦乐书的第241次更新,第254篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第108题(顺位题号是482).您将获得一个表示为字符串S的许可证密钥,该字符串仅包含字 ...

  8. .NET ORM框架之NHibernate

    这段时间一直使用NHibernate,今天抽空总结一下. 1.什么是NHibernate? NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/r ...

  9. Linux运维期中架构(50台集群)

    一.期中架构 二.期中架构-前端部分 三.第三阶段作业-期中架构

  10. 【题解】P1119 灾后重建

    题目地址 理解Floyed的本质 Floyed的本质是动态规划. 在地K次循环中,Floyed算法枚举任意点对(X,Y),在这之前,K从未做过任何点对的中点.因此,可以利用K为中转的路径长度更新. 在 ...