BZOJ4552:[Tjoi2016&Heoi2016]排序
4552: [Tjoi2016&Heoi2016]排序
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 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
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; }