1. 程式人生 > >全國資訊學奧林匹克聯賽(NOIP2016 )複賽模擬(二)

全國資訊學奧林匹克聯賽(NOIP2016 )複賽模擬(二)

                    排序網路
                    Sorter

【問題描述】
最近 Henryy 公司推出了新型的排序網路。簡單的來說,這種排序網路是由
一系列的的排序器按順序組成。某個排序器可以將排序網路中[L,R]之間的輸入
端進行排序。經過排序器處理後[L,R]之間排成非遞減順序。不同排序器的 L、R
值不同。
雖然排序網路很有用,但是很多情況下面我們可能只要排序網路中的最大
值,所以 Henryy 公司決定利用已有的排序網路再開發一個只求最大值的網路。
改造方法很簡單,只需要隱蔽原有網路中的某些排序器,使得最後一個輸入端的
值是最大值。這樣一來既可以減少開發成本,又可以降低網路的功耗。
現在的任務是,給定 N 個不同的排序器,要求你改造這個網路,使得網路
最後一個輸入端經過操作後是這個網路的最大值。要求使用的排序器要儘可能
少。 (也就是說,不能改變原來排序網路的結構,你可以選擇某個排序器是否隱
蔽)
【 輸入檔案】 】
第一行是兩個數 N,M。N 表示排序網路有 N 個輸入端。接下來將會有 M
行,每行 2 個數 Li,Ri,分別表示排序器 I 排序的範圍[Li,Ri]。 (,
1<=Li<=Ri<=N)
【 輸出檔案】 】
輸出一個數 P,表示使用的最少排序器。-1 表示無解(由於設計缺陷) 。
【 樣例輸入】 】
40 6
20 30
1 10
10 20
20 30
15 25
30 40
【 樣例輸出】 】
4
【 資料約定】 】
0≤N≤50000,0≤M≤500000。
對於 30%的資料有 N≤100。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
const int N=50010;
int Min[N<<2],pos[N];
#define mid (l+r>>1)
void Build(int x,int l,int r){
    if
(l==r){ pos[l]=x; if(l==1)Min[x]=0; else Min[x]=(int)1e9; } else{ Build(x<<1,l,mid); Build(x<<1|1,mid+1,r); Min[x]=min(Min[x<<1],Min[x<<1|1]); } } int Query(int x,int l,int r,int a,int b){ if(l>=a&&r<=b)return
Min[x];int ret=(int)1e9; if(mid>=a)ret=min(ret,Query(x<<1,l,mid,a,b)); if(mid<b)ret=min(ret,Query(x<<1|1,mid+1,r,a,b)); return ret; } void Update(int g,int d){ int x=pos[g];Min[x]=min(Min[x],d); while(x>>=1,x)Min[x]=min(Min[x<<1],Min[x<<1|1]); } int n,m,l,r; int main(){ freopen("sorter.in","r",stdin); freopen("sorter.out","w",stdout); scanf("%d%d",&n,&m); Build(1,1,n); while(m--){ scanf("%d%d",&l,&r); if(l==r)continue; Update(r,Query(1,1,n,l,r-1)+1); } if(Min[pos[n]]!=((int)1e9)) printf("%d\n",Min[pos[n]]); else puts("-1"); return 0; }