• 排序网络


    题目描述

    最近 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;
    }
  • 相关阅读:
    解决linux下fflush(stdin)无效
    《转载》使用Chrome浏览器截取整个网页
    JDK切换版本
    消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例
    Oracle 账户
    Oracle linux 安装 相关
    Android高德地图获取当前缩放等级及可视区域四个角的坐标
    Intellij idea 导入项目之后编译错误:无效的源版本:7
    数据库异常整理:org.hibernate.QueryException: could not resolve property: “mStation”
    MySQL(六)多表查询
  • 原文地址:https://www.cnblogs.com/rlddd/p/9851802.html
Copyright © 2020-2023  润新知