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
 
特派员好gin啊,竟然直接出鏼爷BC的题(竟然连样例都没改)
直接处理很难做,我们发现可以二分答案,这样对于01序列我们是很方便排序的,用棵线段树随便搞搞就行了。
时间复杂度为O(Mlog^2N)
  1. #include<cstdio>
  2. #include<cctype>
  3. #include<queue>
  4. #include<cstring>
  5. #include<algorithm>
  6. #define rep(i,s,t) for(int i=s;i<=t;i++)
  7. #define dwn(i,s,t) for(int i=s;i>=t;i--)
  8. #define ren for(int i=first[x];i;i=next[i])
  9. using namespace std;
  10. const int BufferSize=1<<16;
  11. char buffer[BufferSize],*head,*tail;
  12. inline char Getchar() {
  13. if(head==tail) {
  14. int l=fread(buffer,1,BufferSize,stdin);
  15. tail=(head=buffer)+l;
  16. }
  17. return *head++;
  18. }
  19. inline int read() {
  20. int x=0,f=1;char c=Getchar();
  21. for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
  22. for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
  23. return x*f;
  24. }
  25. const int maxn=100010;
  26. int n,m,k,A[maxn];
  27. int setv[maxn<<2],sumv[maxn<<2];
  28. void maintain(int o,int l,int r) {
  29. if(setv[o]>=0) sumv[o]=(r-l+1)*setv[o];
  30. else sumv[o]=sumv[o<<1]+sumv[(o<<1)|1];
  31. }
  32. void pushdown(int o) {
  33. if(setv[o]>=0) {
  34. int lc=o<<1,rc=lc|1;
  35. setv[lc]=setv[rc]=setv[o];
  36. setv[o]=-1;
  37. }
  38. }
  39. void build(int o,int l,int r,int x) {
  40. if(l==r) setv[o]=(A[l]<=x);
  41. else {
  42. setv[o]=-1;
  43. int mid=l+r>>1,lc=o<<1,rc=lc|1;
  44. build(lc,l,mid,x);build(rc,mid+1,r,x);
  45. }
  46. maintain(o,l,r);
  47. }
  48. void update(int o,int l,int r,int ql,int qr,int val) {
  49. if(ql<=l&&r<=qr) setv[o]=val;
  50. else {
  51. pushdown(o);
  52. int mid=l+r>>1,lc=o<<1,rc=lc|1;
  53. if(ql<=mid) update(lc,l,mid,ql,qr,val);
  54. else maintain(lc,l,mid);
  55. if(qr>mid) update(rc,mid+1,r,ql,qr,val);
  56. else maintain(rc,mid+1,r);
  57. }
  58. maintain(o,l,r);
  59. }
  60. int query(int o,int l,int r,int ql,int qr) {
  61. if(setv[o]>=0) return setv[o]*(min(qr,r)-max(ql,l)+1);
  62. if(ql<=l&&r<=qr) return sumv[o];
  63. int mid=l+r>>1,lc=o<<1,rc=lc|1,ans=0;
  64. if(ql<=mid) ans+=query(lc,l,mid,ql,qr);
  65. if(qr>mid) ans+=query(rc,mid+1,r,ql,qr);
  66. return ans;
  67. }
  68. int ty[maxn],ql[maxn],qr[maxn];
  69. int check(int x) {
  70. build(1,1,n,x);
  71. rep(i,1,m) {
  72. int res=query(1,1,n,ql[i],qr[i]);
  73. if(!res||res==qr[i]-ql[i]+1) continue;
  74. if(ty[i]) {
  75. update(1,1,n,ql[i],qr[i]-res,0);
  76. update(1,1,n,qr[i]-res+1,qr[i],1);
  77. }
  78. else {
  79. update(1,1,n,ql[i],ql[i]+res-1,1);
  80. update(1,1,n,ql[i]+res,qr[i],0);
  81. }
  82. }
  83. return query(1,1,n,k,k);
  84. }
  85. int main() {
  86. n=read();m=read();
  87. rep(i,1,n) A[i]=read();
  88. rep(i,1,m) ty[i]=read(),ql[i]=read(),qr[i]=read();
  89. k=read();
  90. int l=1,r=n,mid;
  91. while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
  92. printf("%d\n",l);
  93. return 0;
  94. }

  

BZOJ4552: [Tjoi2016&Heoi2016]排序的更多相关文章

  1. bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序

    http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ...

  2. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  3. BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】

    题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...

  4. [bzoj4552][Tjoi2016][Heoi2016]排序

    Description 给出一个$1$到$n$的全排列,现在对这个全排列序列进行$m$次局部排序,排序分为$2$种: $1.(0,l,r)$表示将区间$[l,r]$的数字升序排序; $2.(1,l,r ...

  5. [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树

    Brief Description DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列. 现在他想支持两种操作: 0, l, r: 将a[l..r]原地升序排序. 1, l, r: 将a ...

  6. BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  7. 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)

    传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ...

  8. BZOJ4552 Tjoi2016&Heoi2016排序 【二分+线段树】*

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个 ...

  9. [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)

    二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可 然后询问第q个位置的值,为1说明>=mid,以上 时间复杂度O(nlog2 ...

随机推荐

  1. Delphi线程基础知识

    参考http://blog.chinaunix.net/uid-10535208-id-2949323.html 一.概述 Delphi提供了好几种对象以方便进行多线程编程.多线程应用程序有以下几方面 ...

  2. scala的tcp通信

    client: object ActorClient extends App { import actors.Actor, actors.remote.Node, actors.remote.Remo ...

  3. ThinkPHP中getField( )和field( )

    做数据库查询的时候,比较经常用到这两个,总是查手册,记不住,现在把它总结下,希望以后用的时候不查手册了. 不管是用select 查询数据集,还是用find 查询数据,常配合连贯操作where.fiel ...

  4. HR外包系统 - 员工项目 薪资项目 考勤项目 -管理

    项目管理-包括员工项目 薪资项目 考勤项目 一 后台总公司定义项目-前台分公司选择项目,定义别名-分公司客户选择员工项目,定义别名 分公司下面-新建薪资类别-薪资类别下面选择要的薪资和考勤项目. 二 ...

  5. 进程控制理论,王明学learn

    进程控制理论 一.进程 进程是一个具有一定独立功能程序的一次运行活动. 1.1进程特点 1.动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的 2.并发性:任何进程都可以同其他进程一起 ...

  6. IMAGE_LOAD_CONFIG_DIRECTORY64 SafeSEH检测 表

    IMAGE_LOAD_CONFIG_DIRECTORY64 typedef struct { DWORD Size; DWORD TimeDateStamp; WORD MajorVersion; W ...

  7. matlab报错

    这可能说明..压根就没有这个函数

  8. 用JAXP的SAX方式解析XML文件

    简单用JAXP的SAX方式(事件驱动)解析XML文件: 文件(1.XML) <?xml version="1.0" encoding="UTF-8" st ...

  9. Dialog+NumberPicker

      package com.gtercn.myapplication; import android.app.Activity; import android.content.DialogInterf ...

  10. mongodb学习02基础知识

    文档 键值对的一个有序集 文档被表示为对象 文档必须有一个 _id 键 {"greeting" : "Hello, world!"}` 键 文档的键是字符串 区 ...