BZOJ 4552 [Tjoi2016&Heoi2016]排序
来源:互联网 发布:js绑定事件的方法区别 编辑:程序博客网 时间:2024/06/09 16:10
BZOJ 4552 [Tjoi2016&Heoi2016]排序
题目描述
在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q位置上的数字。输入输出格式
输入格式:
输入数据的第一行为两个整数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
输出格式:
输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。
输入输出样例
输入样例#1:
6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
输出样例#1:
5
说明
河北省选2016第一天第二题。原题的时限为6s,但是洛谷上是1s,所以洛谷的数据中,对于30%的数据,有 n,m<=1000,对于100%的数据,有 n,m<=30000
看起来很难搞,那就二分答案。
把小于等于二分数X的置为0,反之置为1,那么排序就成为将区间内前Len-sum位置为0,后sum位置为1,线段树解决。
其实就是个套路。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN=1e5+5,INF=0x3f3f3f3f; struct Op{int L,R,Kind;}Q[MAXN]; int Sum[MAXN<<2],A[MAXN],N,M,Ql,Qr,Down[MAXN<<2],T[MAXN],Val,P; inline void PushDown(int I,int L,int R) { if(Down[I]!=-1){ int Lc=I<<1,Rc=Lc|1,Mid=(L+R)>>1,Tag=Down[I];Down[I]=-1; Down[Lc]=Down[Rc]=Tag; Sum[Lc]=(Mid-L+1)*Tag,Sum[Rc]=(R-Mid)*Tag; } } inline void PushUp(int I) { Sum[I]=Sum[I<<1]+Sum[I<<1|1]; } void Build(int I,int L,int R) { if(L==R){Sum[I]=T[L];return;} int Mid=(L+R)>>1; Build(I<<1,L,Mid),Build(I<<1|1,Mid+1,R); PushUp(I); } int Query(int I,int L,int R) { if(L>=Ql&&R<=Qr)return Sum[I]; PushDown(I,L,R); int Lc=I<<1,Rc=Lc|1,Mid=(L+R)>>1; if(Qr<=Mid)return Query(Lc,L,Mid); else if(Ql>Mid)return Query(Rc,Mid+1,R); else return Query(Lc,L,Mid)+Query(Rc,Mid+1,R); } void Update(int I,int L,int R) { if(L>=Ql&&R<=Qr){ Sum[I]=Val*(R-L+1); Down[I]=Val; return; } PushDown(I,L,R); int Mid=(L+R)>>1,Lc=I<<1,Rc=Lc|1; if(Qr<=Mid)Update(Lc,L,Mid); else if(Ql>Mid)Update(Rc,Mid+1,R); else Update(Lc,L,Mid),Update(Rc,Mid+1,R); PushUp(I); } inline int Check(int X) { for(int I=1;I<=N;++I) T[I]=(A[I]<=X)?0:1; memset(Down,-1,sizeof(Down)); Build(1,1,N); for(int I=1,T;I<=M;++I){ Ql=Q[I].L,Qr=Q[I].R; T=Query(1,1,N); if(Q[I].Kind==0){ Ql=Q[I].L,Qr=Q[I].R-T,Val=0; if(Ql<=Qr)Update(1,1,N); Ql=Q[I].R-T+1,Qr=Q[I].R,Val=1; if(Ql<=Qr)Update(1,1,N); }else{ Ql=Q[I].L,Qr=Q[I].L+T-1,Val=1; if(Ql<=Qr)Update(1,1,N); Ql=Q[I].L+T,Qr=Q[I].R,Val=0; if(Ql<=Qr)Update(1,1,N); } } Ql=P,Qr=P; return Query(1,1,N); } int main() { scanf("%d%d",&N,&M); for(int I=1;I<=N;++I) scanf("%d",A+I); for(int I=1;I<=M;++I) scanf("%d%d%d",&Q[I].Kind,&Q[I].L,&Q[I].R); scanf("%d",&P); int L=1,R=N,Mid; while(L<=R){ Mid=(L+R)>>1; if(!Check(Mid))R=Mid-1; else L=Mid+1; } printf("%d\n",R+1); return 0; }
阅读全文
0 0
- BZOJ 4552: [Tjoi2016&Heoi2016]排序
- BZOJ 4552 [Tjoi2016&Heoi2016]排序
- BZOJ 4552: [Tjoi2016&Heoi2016]排序
- BZOJ 4552 [Tjoi2016&Heoi2016]排序
- bzoj 4552: [Tjoi2016&Heoi2016]排序
- BZOJ 4552 [Tjoi2016&Heoi2016]排序
- 4552: [Tjoi2016&Heoi2016]排序
- bzoj 4552: [Tjoi2016&Heoi2016]排序 二分答案+线段树
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 线段树+二分
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 二分 线段树
- 【BZOJ】4552 [Tjoi2016&Heoi2016]排序 二分+线段树
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 [二分][线段树]
- BZOJ4552 [Tjoi2016&Heoi2016]排序
- bzoj4552【TJOI2016&HEOI2016】排序
- JZOJ4605. 【TJOI2016&HEOI2016】排序
- 【Tjoi2016&Heoi2016】排序
- 【TJOI2016&&HEOI2016】排序
- 【bzoj4552】 [Tjoi2016&Heoi2016]排序
- 自定义View(四)弹性滑动Scroller
- ruby--$:.unshift File.expand_path('..', __FILE__)
- java中静态初始化块、初始化块和构造方法的理解 (转载)
- 114. Unique Paths
- 网络号和网关
- BZOJ 4552 [Tjoi2016&Heoi2016]排序
- Mybatis入门简版(补充)
- RAM的理解
- 2017年总结
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- MPLS-TP原理
- 迷之集训
- 一种隐藏DLL的方式
- 视频编辑器-MovieMator 简洁使用-在时间线上拆分,修剪,连接剪辑