BZOJ4552:[Tjoi2016&Heoi2016]排序

Posted QYP_2002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4552:[Tjoi2016&Heoi2016]排序相关的知识,希望对你有一定的参考价值。

4552: [Tjoi2016&Heoi2016]排序

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 1058  Solved: 585
[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
思路{
  首先模拟是不行的吧。。。。。。。
  怎么搞呢》》》》》》》23333
  易知那个数满足单调性(废话)
  那我们就赢该二分答案,二分什么呢》
  应当把序列分为01串,然后线段树维护一下,修改乱搞咯。最后比较当前位置与二分答案的大小关系即可。时间复杂度O(logn*(mlog(n)+n))
}
#include<map>
#include<set>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<complex>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define ls (o<<1)
#define rs ((o<<1)|1)
#define maxx 100010
#define RG register
#define mid ((l+r)>>1)
using namespace std;
int tree[maxx*4],a[maxx],n,m,lazy[maxx*4];bool sub[maxx];int sum;
struct ask{
  int l,r,t;
}b[maxx];
void build(int o,int l,int r){
  if(l==r){tree[o]=(sub[l]==1);return;}
  build(ls,l,mid),build(rs,mid+1,r);
  tree[o]=tree[ls]+tree[rs];
}
void down(int o,int l,int r){
  if(lazy[o]!=-1)tree[rs]=(r-mid)*lazy[o],tree[ls]=(mid-l+1)*lazy[o];
  if(lazy[o]!=-1)lazy[rs]=lazy[ls]=lazy[o];lazy[o]=-1;
}
void update(int o,int l,int r,int L,int R,int num){
  if(l!=r)down(o,l,r);
  if(l>=L&&r<=R){tree[o]=num*(r-l+1),lazy[o]=num;return;}
  if(mid<L)update(rs,mid+1,r,L,R,num);
  else if(mid>=R)update(ls,l,mid,L,R,num);
  else update(rs,mid+1,r,L,R,num),update(ls,l,mid,L,R,num);
  tree[o]=tree[ls]+tree[rs];
}
int query(int o,int l,int r,int L,int R){
  if(l!=r)down(o,l,r);
  if(l>=L&&r<=R)return tree[o];
  if(mid<L)return query(rs,mid+1,r,L,R);
  else if(mid>=R)return query(ls,l,mid,L,R);
  else return query(rs,mid+1,r,L,R)+query(ls,l,mid,L,R);
}int pos;
int main(){
  scanf("%d%d",&n,&m);int l=66666666,r=-666666666;
  for(int i=1;i<=n;++i)scanf("%d",&a[i]),l=min(l,a[i]),r=max(r,a[i]);
  for(int i=1;i<=m;++i)scanf("%d%d%d",&b[i].t,&b[i].l,&b[i].r);scanf("%d",&pos);
  while(l<=r){memset(lazy,-1,sizeof(lazy));
    for(RG int i=1;i<=n;++i)if(a[i]>mid)sub[i]=1;else sub[i]=0;
    build(1,1,n);
    for(RG int i=1;i<=m;++i){
      sum=query(1,1,n,b[i].l,b[i].r);
      if(b[i].t){
    if(sum)update(1,1,n,b[i].l,b[i].l+sum-1,1);
    if(sum!=b[i].r-b[i].l+1)update(1,1,n,b[i].l+sum,b[i].r,0);
      }
      else{
    if(sum)update(1,1,n,b[i].r-sum+1,b[i].r,1);
    if(sum!=b[i].r-b[i].l+1)update(1,1,n,b[i].l,b[i].r-sum,0);
      }
    }int axx=query(1,1,n,pos,pos);
    if(!axx)r=mid-1;else l=mid+1;
  }cout<<l;return 0;
}

 

以上是关于BZOJ4552:[Tjoi2016&Heoi2016]排序的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4552][TJOI2016&&HEOI2016]排序

BZOJ4552:[Tjoi2016&Heoi2016]排序

[BZOJ] 4552: [Tjoi2016&Heoi2016]排序 #二分+线段树+算法设计策略

bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案

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

Bzoj4552: [Tjoi2016&Heoi2016]排序