排序网络

题目描述

最近 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。



题解

线段树。

题意其实就是按输入顺序找出几个区间使它们覆盖[ 1,n ] 。

那么找到的第一个区间的左端点一定是 1 。

以后每个区间的答案可以由它覆盖到的前面的区间的最小答案+1更新而来。

复杂度O(mlogn)。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=50000+50;
const int inf=2e9;

int n,m,pos[maxn];

struct SegmentTree{int l,r,mn;}st[maxn<<2];

void pushup(int root){
    st[root].mn=min(st[root<<1].mn,st[root<<1|1].mn);
}

void build(int root,int l,int r){
    st[root].l=l;st[root].r=r;
    if(l==r){
        pos[l]=root;
        if(l==1) st[root].mn=0;
        else st[root].mn=inf;
    }
    else{
        int m=l+r>>1;
        build(root<<1,l,m);build(root<<1|1,m+1,r);
        pushup(root);
    }
}

int query(int root,int l,int r){
    if(st[root].l>r||st[root].r<l) return inf;
    if(st[root].l>=l&&st[root].r<=r) return st[root].mn;
    return min(query(root<<1,l,r),query(root<<1|1,l,r));
}

void update(int x,int val){
    int root=pos[x];
    st[root].mn=min(st[root].mn,val);
    while(root>>=1&&root) pushup(root);
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
//    freopen("sorter.in","r",stdin);
//    freopen("sorter.out","w",stdout);
    read(n),read(m);
    build(1,1,n);
    while(m--){
        int l,r;
        read(l),read(r);
        if(l==r) continue;
        update(r,query(1,l,r-1)+1);
    }
    if(st[pos[n]].mn!=inf){
        cout<<st[pos[n]].mn<<endl;
    }
    else cout<<-1<<endl;
//  noip 2018 rp ++
    return 0;
}
原文地址:https://www.cnblogs.com/rlddd/p/9851802.html