4552: [Tjoi2016&Heoi2016]排序

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 2703  Solved: 1386
[Submit][Status][Discuss]

Description

在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
位置上的数字。

Input

输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
,1 <= m <= 10^5

Output

输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

Sample Input

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

Sample Output

5

这题直接排序肯定T到飞起,然后我们考虑其他做法(废话)
瞎yy仔细分析后这也是个区间问题阿,考虑能不能用线段树维护。
发现说是排序,但是最主要的关系还是之和大小关系有关啊,所以把这个问题抽象成一个01序列
我们可以二分答案,每次check都把所有操作重新进行一遍。这只是个大体思路,我们还要考虑其正确性。
为什么要二分答案,因为把问题转化成01序列后0或1代表该数与目标的大小关系,如果当前的该位置比目标大,那肯定是将区间左断点变大啊
至于决策单调性,博主比较mengbi。有大佬会可以指出阿
现在我们考虑怎么对每个更改进行操作,前面我们说过,01代表的是某个数与目标的大小关系,那我们在排序时只需利用这个性质,对于升序排序,把区间中所有0甩到左边,把1甩到右边,如果降序反过来。
这样我们在二分答案时只需检测询问位置是否为1即可。
对于这这些操作只需维护一棵支持区间覆盖,区间修改的线段数即可。
注意点:在懒标记下传和赋值时,要直接赋值而不是累加。
    要加特判(代码中有注释),因为check()函数中的 change(1,1,n,ql[i],ql[i]+num-1,1)会导致右端点小于左端点
 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
const int N=1e5+;
using namespace std;
int mid,sum1,q;
int n,m;
int a[N];
struct node{
int l,r,opt;
}ask[N];
struct NODE{
int l,r,val,f;
}tr[N<<];
void build(int p,int l,int r){//cout<<"B"<<endl;
tr[p].l=l,tr[p].r=r;
if(l==r){//cout<<"break"<<endl;
tr[p].f=-;
tr[p].val=(a[l]>=mid);
return ;
}
tr[p].f=-;
int mid=(l+r)>>;
build(p<<,l,mid);
build(p<<|,mid+,r);
tr[p].val=tr[p<<].val+tr[p<<|].val;
}
void down(int p){
if(tr[p].f<) return ;
tr[p<<].f=tr[p].f;
tr[p<<|].f=tr[p].f;//lanbiaojizhijiefugai
tr[p<<].val=(tr[p<<].r-tr[p<<].l+)*tr[p].f;
tr[p<<|].val=(tr[p<<|].r-tr[p<<|].l+)*tr[p].f;
tr[p].f=-;
}
void change(int p,int l,int r,int val){
if(l<=tr[p].l&&tr[p].r<=r){
tr[p].f=val;
tr[p].val=(tr[p].r-tr[p].l+)*val;//zhijiefuzhi//
return ;
}
if(l>tr[p].r||r<tr[p].l) return ;
down(p);
int mid=(tr[p].l+tr[p].r)>>;
if(l<=mid) change(p<<,l,r,val);
if(r>mid) change(p<<|,l,r,val);
tr[p].val=tr[p<<].val+tr[p<<|].val;
}
void query(int p,int l,int r){//cout<<p<<" "<<l<<" "<<r<<endl;
if(l<=tr[p].l&&tr[p].r<=r){//cout<<"break"<<endl;
sum1+=tr[p].val;//
return ;
}
if(l>tr[p].r||r<tr[p].l) return ;//特判
down(p);
int mid=(tr[p].l+tr[p].r)>>;
if(l<=mid)query(p<<,l,r);
if(r>mid)query(p<<|,l,r);
}
bool check(int x){
build(,,n);
for(int i=;i<=m;i++){
sum1=;query(,ask[i].l,ask[i].r);
if(ask[i].opt==){//升序
//cout<<"Q"<<endl;
change(,ask[i].l,ask[i].r-sum1,);//
change(,ask[i].r-sum1+,ask[i].r,);//
}
else{
//cout<<"Q"<<endl;
change(,ask[i].l+sum1,ask[i].r,);
change(,ask[i].l,ask[i].l+sum1-,);
}
}
//for(int i=1;i<=n;i++) cout<<tr[i].val<<" ";
sum1=;
query(,q,q);
//cout<<sum1<<endl;
if(sum1) return true;
else return false;
}
int main(){
//freopen("sort9.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=m;i++){
scanf("%d%d%d",&ask[i].opt,&ask[i].l,&ask[i].r);
}
scanf("%d",&q);
int l=,r=n,ans;
while(l<r){//cout<<"K"<<endl;
mid=(l+r)>>;//cout<<l<<" "<<r<<" "<<mid<<endl;
//cout<<check(mid)<<endl;
if(check(mid)) ans=mid/*?*/,l=mid+;
else r=mid;
}
printf("%d",ans);
}

[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. luoguP2824 [HEOI2016/TJOI2016]排序(线段树分裂做法)

    题意 所谓线段树分裂其实是本题的在线做法. 考虑如果我们有一个已经排好序的区间的权值线段树,那么就可以通过线段树上二分的方法得到第\(k\)个数是谁. 于是用set维护每个升序/降序区间的左右端点以及 ...

  4. 洛谷$P2824\ [HEOI2016/TJOI2016]$ 排序 线段树+二分

    正解:线段树+二分 解题报告: 传送门$QwQ$ 昂着题好神噢我$jio$得$QwQQQQQ$,,, 开始看到长得很像之前考试题的亚子,,,然后仔细康康发现不一样昂$kk$,就这里范围是$[1,n]$ ...

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

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

  6. Luogu P2824 [HEOI2016/TJOI2016]排序 线段树+脑子

    只会两个$log$的$qwq$ 我们二分答案:设答案为$ans$,则我们把$a[i]<=ans$全部设成$0$,把$a[i]>ans$全部设成$1$,扔到线段树里,这样区间排序(升序)就是 ...

  7. day 1 晚上 P2824 [HEOI2016/TJOI2016]排序 线段树

    #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #inclu ...

  8. 排序HEOI2016/TJOI2016 二分+线段树判定

    LINK:排序 此题甚好我一点思路都没有要是我当时省选此题除了模拟我恐怕想不到还可以二分 还可以线段树... 有点ex 不太好写 考虑 暴力显然每次给出询问我们都是可以直接sort的 无视地形无视一切 ...

  9. BZOJ4552 HEOI/TJOI2016 排序 线段树、二分答案

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意:给出一个$1$到$N$的全排列,对其进行$M$次排序,每次排序将区间$[l ...

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

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

随机推荐

  1. python爬虫实战--抖音

    申明&警告: 请在相关网站的许可范围内爬取数据.以免影响网站正常运行, 如果我的文章有触犯权益的地方, 请告知删除. 上一篇爬取知乎的文章基本就是大多数网站的爬取思路了(headers部分其实 ...

  2. X86逆向1:软件破解入门课【课件下载】

    从本节课开始,我将带领小白入门学习软件破解的相关内容,大佬绕过,以后将会定期更新从最基本的破解知识点开始学习,由简单到复杂循序渐进,难度会逐步提高. 为了防止版权方面的争议,我将自行编写一些破解案例来 ...

  3. c# TCP/IP协议利用Socket Client通信(只含客户端Demo)

    完全是基础,新手可以随意看看,大牛可以关闭浏览页了,哈哈. TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. ...

  4. C# 使用Emit实现动态AOP框架 进阶篇之优化

    目  录 C# 使用Emit实现动态AOP框架 (一) C# 使用Emit实现动态AOP框架 (二) C# 使用Emit实现动态AOP框架 (三) C# 使用Emit实现动态AOP框架 进阶篇之异常处 ...

  5. NetScaler循环抓包设置

    NetScaler循环抓包设置 来源 https://raynorli.com/2018/07/01/netscaler-nstrace-cycling-capture/ 参考文档 How to Re ...

  6. windows服务总结

    一.创建windows服务项目创建完成后结构,如: 其中,Program.cs代码: using System; using System.Collections.Generic; using Sys ...

  7. vue入门:(条件渲染)

    v-if v-show v-else 一.v-if:生成或者移出一个元素 <div id="example"> <button v-on:click=" ...

  8. TCP保活定时器

    TCP有Keepalive功能,它和HTTP的Keepalive功能目的不一样.TCP服务器希望知道客户端是否崩溃.重新启动或者中间路由不通.保活定时器就提供这种功能. 在进一步介绍TCP的保活定时器 ...

  9. KMS激活的密钥

    今天办公电脑黑屏了,仔细一看,变成了未激活.于是从网上找到了所有Windows版本的GVLK密钥,试了一下完美激活,应该是180天的吧.先用着,等下次过期了再说,哈哈. GVLK密钥是专门用于KMS激 ...

  10. GNU编译器:Codesourcery

    Codesourcery G++是个商业软件, 不过它有个lite版本,是完全免费的,只不过没有IDE,只有commmand line. Codesourcery G++支持coldfire, pow ...