「TJOI / HEOI2016」排序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Stevencwehf/article/details/102662682

题意:在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。

这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:

1:(0,l,r)表示将区间[l,r]的数字升序排序

2:(1,l,r)表示将区间[l,r]的数字降序排序

最后询问第q位置上的数字。

思路 这道题常规思路是直接暴力 (当然超时是肯定的)
于是在这里我么考虑将答案二分 然后将原序列转为储存元素与该值大小关系的 01序列。然后考虑01序列排序,这个是可以O(logn)实现的。只需要对序列建线段树,然后统计区间 1
的个数,并按序区间赋值即可。查询的时候直接线段树单点询P 位置的元素是否为 1 以调整二分上下界。

上代码`

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+1000;
#define lc (p<<1)
#define rc (p<<1|1)
inline int read()
{
    int data=0;int w=1; char ch=0;
    ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return data*w;
}
int n,m;
int a[N],pos;
struct opt{
	int l,r,op;
	opt() {}
	opt(int _l, int _r, int _op) : l(_l), r(_r), op(_op){}
}q[N];
struct node{
	int p,l,r,sum,tag;
}t[N<<2];
inline void pushup(int p){t[p].sum=t[lc].sum+t[rc].sum;}
inline void pushdown(int p,int l,int r){
	if(~t[p].tag){
		t[lc].tag=t[rc].tag=t[p].tag;
	    int mid=(l+r)>>1;
	    if(t[p].tag) t[lc].sum=mid-l+1,t[rc].sum=r-mid;
	    else t[lc].sum=t[rc].sum=0;
	    t[p].tag=-1;
	}
}
inline void build(int p,int l,int r,int x){
	t[p].l=l;t[p].r=r;t[p].tag=-1;
	if(l==r) {
		t[p].sum=(a[l]>=x);return;
	}
	int mid=(l+r)>>1;
	build(lc,l,mid,x);build(rc,mid+1,r,x);pushup(p); 
}
inline int query(int p,int L,int R){
	int l=t[p].l,r=t[p].r;
	if(L>r||R<l) return 0;
	if(l>=L&&r<=R) return t[p].sum;
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	int res=0;
	if(L<=mid) res+=query(lc,L,R);
	if(R>mid) res+=query(rc,L,R);
	return res;
}
inline int que(int p,int pos){
	int l=t[p].l,r=t[p].r;
	if(l==r) return t[p].sum;
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(pos<=mid) return que(lc,pos);
	else return que(rc,pos);
}
inline void modify(int p,int L,int R,int x){
	int l=t[p].l,r=t[p].r;
	if(l>=L&&r<=R) {
		t[p].sum=x*(r-l+1);t[p].tag=x;return;
	} 
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(L<=mid) modify(lc,L,R,x);
	if(R>mid) modify(rc,L,R,x);
	pushup(p);
}
bool check(int x){
	build(1,1,n,x);
	for(register int i=1;i<=m;i++){
		int len=query(1,q[i].l,q[i].r);
		if(!q[i].op){
			modify(1,q[i].l,q[i].r-len,0);
			modify(1,q[i].r-len+1,q[i].r,1);
		}
		else{
			modify(1,q[i].l,q[i].l+len-1,1);
			modify(1,q[i].l+len,q[i].r,0);
		}
	}
	return que(1,pos);
}
int main(){
     n=read();m=read();
	 for(int i=1;i<=n;i++) a[i]=read();
	 for(int i=1;i<=m;i++){int op=read(),l=read(),r=read();q[i]=opt(l,r,op);}	
	 pos=read(); 
	 int l=1,r=n,ans;
	 while(l<r){
	 	 int mid=(l+r)>>1;
	 	 if(check(mid)) ans=mid,l=mid+1;
	 	 else r=mid;
	 }
	 printf("%d\n",ans);
	return 0; 
} 

猜你喜欢

转载自blog.csdn.net/Stevencwehf/article/details/102662682