BZOJ4552: [Tjoi2016&Heoi2016]排序


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)
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
	if(head==tail) {
		int l=fread(buffer,1,BufferSize,stdin);
		tail=(head=buffer)+l;
	}
	return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=100010;
int n,m,k,A[maxn];
int setv[maxn<<2],sumv[maxn<<2];
void maintain(int o,int l,int r) {
	if(setv[o]>=0) sumv[o]=(r-l+1)*setv[o];
	else sumv[o]=sumv[o<<1]+sumv[(o<<1)|1];
}
void pushdown(int o) {
	if(setv[o]>=0) {
		int lc=o<<1,rc=lc|1;
		setv[lc]=setv[rc]=setv[o];
		setv[o]=-1;
	}
}
void build(int o,int l,int r,int x) {
	if(l==r) setv[o]=(A[l]<=x);
	else {
		setv[o]=-1;
		int mid=l+r>>1,lc=o<<1,rc=lc|1;
		build(lc,l,mid,x);build(rc,mid+1,r,x);
	}
	maintain(o,l,r);
}
void update(int o,int l,int r,int ql,int qr,int val) {
	if(ql<=l&&r<=qr) setv[o]=val;
	else {
		pushdown(o);
		int mid=l+r>>1,lc=o<<1,rc=lc|1;
		if(ql<=mid) update(lc,l,mid,ql,qr,val);
		else maintain(lc,l,mid);
		if(qr>mid) update(rc,mid+1,r,ql,qr,val);
		else maintain(rc,mid+1,r);
	}
	maintain(o,l,r);
}
int query(int o,int l,int r,int ql,int qr) {
	if(setv[o]>=0) return setv[o]*(min(qr,r)-max(ql,l)+1);
	if(ql<=l&&r<=qr) return sumv[o];
	int mid=l+r>>1,lc=o<<1,rc=lc|1,ans=0;
	if(ql<=mid) ans+=query(lc,l,mid,ql,qr);
	if(qr>mid) ans+=query(rc,mid+1,r,ql,qr);
	return ans;
}
int ty[maxn],ql[maxn],qr[maxn];
int check(int x) {
	build(1,1,n,x);
	rep(i,1,m) {
		int res=query(1,1,n,ql[i],qr[i]);
		if(!res||res==qr[i]-ql[i]+1) continue;
		if(ty[i]) {
			update(1,1,n,ql[i],qr[i]-res,0);
			update(1,1,n,qr[i]-res+1,qr[i],1);
		}
		else {
			update(1,1,n,ql[i],ql[i]+res-1,1);
			update(1,1,n,ql[i]+res,qr[i],0);
		}
	}
	return query(1,1,n,k,k);
}
int main() {
	n=read();m=read();
	rep(i,1,n) A[i]=read();
	rep(i,1,m) ty[i]=read(),ql[i]=read(),qr[i]=read();
	k=read();
	int l=1,r=n,mid;
	while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
	printf("%d\n",l);
	return 0;
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM