1. 程式人生 > >[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

urn names node 降序排序 zoj 研究 log i++ name

題目描述

在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位置上的數字。

(luogu數據,30000)

題解:

確實開始比較沒有思路。

不像某JZOJ模擬題,可以線段樹維護區間內每個字符的個數。

但是這一共30000個字符啊!!!沒辦法乖乖排序

發現,突破口是,最後只要知道q位置是什麽就可以!

神仙思路:

我們二分一個q位置的值mid,把所有的小於的值的位置賦值為1,否則就是0

然後循環m,0/1排序就比較方便了。線段樹,找到區間有多少個1,多少個0,把所有的0放左邊,然後放1(降序的話反過來)

最後,如果q位置是1,那麽ans=mid,r=mid-1;

如果q位置是0,那麽l=mid+1

復雜度O(nlog^2n)

代碼:

#include<bits/stdc++.h>
#define mid ((l+r)>>1)
using namespace std;
const int N=30000+4;
int a[N];
int b[N];
int n,m;
struct node{
    int sum;
    int ch;
}t[4*N];
int q[N][3];
int pos;
void pushdown(int x,int l,int r){
    if(t[x].ch==-1) return;
    t[x<<1].ch=t[x].ch;
    t[x
<<1|1].ch=t[x].ch; t[x<<1].sum=t[x].ch*(mid-l+1); t[x<<1|1].sum=t[x].ch*(r-mid); t[x].ch=-1; } void build(int x,int l,int r){ if(l==r){ t[x].ch=-1; t[x].sum=b[l]; return; } t[x].ch=-1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); t[x].sum=t[x<<1].sum+t[x<<1|1].sum; } int query(int x,int l,int r,int L,int R){ if(L<=l&&r<=R){ return t[x].sum; } pushdown(x,l,r); int ret=0; if(L<=mid) ret+=query(x<<1,l,mid,L,R); if(mid<R) ret+=query(x<<1|1,mid+1,r,L,R); return ret; } void chan(int x,int l,int r,int L,int R,int c){ if(L<=l&&r<=R){ t[x].ch=c; t[x].sum=(r-l+1)*c; return; } pushdown(x,l,r); if(L<=mid) chan(x<<1,l,mid,L,R,c); if(mid<R) chan(x<<1|1,mid+1,r,L,R,c); t[x].sum=t[x<<1].sum+t[x<<1|1].sum; } 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][0],&q[i][1],&q[i][2]); } scanf("%d",&pos); int l=1,r=n; int ans; while(l<=r){ int MID=(l+r)>>1; for(int i=1;i<=n;i++){ if(a[i]>=MID) b[i]=1; else b[i]=0; //cout<<b[i]<<" "; }//cout<<endl; build(1,1,n); //cout<<l<<" "<<r<<" mid "<<MID<<endl; for(int i=1;i<=m;i++){ //cout<<i<<" "<<q[i][1]<<" "<<q[i][2]<<endl; int sum1=query(1,1,n,q[i][1],q[i][2]); int sum0=q[i][2]-q[i][1]+1-sum1; //cout<<" sum "<<sum1<<" "<<sum0<<endl; if(q[i][0]){//down chan(1,1,n,q[i][1],q[i][1]+sum1-1,1); chan(1,1,n,q[i][1]+sum1,q[i][2],0); } else{//up chan(1,1,n,q[i][1],q[i][1]+sum0-1,0); chan(1,1,n,q[i][1]+sum0,q[i][2],1); } } int lp=query(1,1,n,pos,pos); if(lp==1) ans=MID,l=MID+1; else r=MID-1; } printf("%d",ans); return 0; }

[HEOI2016/TJOI2016]排序