[HEOI2016/TJOI2016]排序
題目描述
在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位置上的數字。
輸入輸出樣例
輸入樣例#1:
6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
輸出樣例#1:
5
說明
對于30%的數據,有 n,m<=1000,對于100%的數據,有 n,m<=30000
首先,這道題只有一組查詢,所以可以二分這個數的排名
每次二分一個要查詢的數在序列中的大小排名
(排名指在升序的情況下的排名)
然后當val[i] >= mid 此位置就為1 反之則為0 這樣一來,這道題就變成了一個01序列排序,所以就可以用線段樹實現logn排序
線段樹維護區間和,需要實現區間覆蓋
每次排序前先查詢排序一共有多少1
升序排序則將r-區間1的數量+1~r改為1 l~ r-區間1的數量改為0
最后再查詢要詢問的位置
若要查詢的位置為1,那么就增加ta的排名(r=mid-1)
反之,就降低這個數排名
由于這個數列是1~n的全排列,所以二分出的結果就是答案
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> # define ls now<<1 # define rs now<<1|1 const int M = 30005 ; using namespace std; inline int read(){char c=getchar(); int x=0,w=1;while(c>'9'||c<'0'){if(c=='-') w=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*w; } struct Q{int opt,l,r; }q[M]; int n,m,st[M],val[M],tag[M<<2],tree[M<<2],K; inline void pushup(int now){tree[now]=tree[ls]+tree[rs]; } void build(int l,int r,int now){tag[now]=-1;if(l==r){tree[now]=st[l];return ;}int mid=(l+r)>>1;build(l,mid,ls); build(mid+1,r,rs);pushup(now); } inline void pushdown(int now,int l,int r){if(tag[now]<0) return ;tag[ls]=tag[rs]=tag[now];tree[ls]=tag[now]*l; tree[rs]=tag[now]*r;tag[now]=-1; } void change(int L ,int R ,int val,int l,int r,int now){if(l>R||r<L) return ;if(l>=L&&r<=R){tree[now]=val*(r-l+1);tag[now]=val; return ;}int mid=(l+r)>>1;pushdown(now,mid-l+1,r-mid);change(L,R,val,l,mid,ls);change(L,R,val,mid+1,r,rs);pushup(now); } int query(int L, int R,int l,int r,int now){if(l>R||r<L) return 0;if(l>=L&&r<=R) return tree[now];int mid=(l+r)>>1;pushdown(now,mid-l+1,r-mid);int Ans=0;Ans+=query(L, R, l,mid,ls);Ans+=query(L, R, mid+1,r,rs);return Ans; } inline int judge(int mid){for(register int i=1;i<=n;++i)if(val[i]>=mid) st[i]=1;else st[i]=0;build(1,n,1);for(register int i=1;i<=m;++i){int l =q[i].l, r= q[i].r ;if(q[i].opt==0){// 升序排列 int num1=query(l,r,1,n,1);change(r-num1+1,r,1,1,n,1);change(l,r-num1,0,1,n,1);}else{// 降序排列int num1=query(l,r,1,n,1);change(l,l+num1-1,1,1,n,1);change(l+num1,r,0,1,n,1);}}int tmp=query(K,K,1,n,1);return tmp; } int main(){n=read(); m=read();for(register int i=1;i<=n;++i) val[i]=read();for(register int i=1;i<=m;++i){q[i].opt=read(); q[i].l=read(); q[i].r=read();}K = read() ;int L=1 , R=n , Ans=0;while(L<=R){int mid=(L+R)>>1;if(judge(mid)) L=mid+1,Ans=mid ;else R=mid-1;}printf("%d\n",Ans);return 0; }轉載于:https://www.cnblogs.com/beretty/p/9478704.html
總結
以上是生活随笔為你收集整理的[HEOI2016/TJOI2016]排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2018新版正方教务 ---爬虫---
- 下一篇: post提交的数据几种编码格式