zoukankan      html  css  js  c++  java
  • [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
    ",Ans);
        return 0;
    }
    
    
  • 相关阅读:
    MySQL中默认值中用时间函数的问题
    mysql数据表的操作
    mysql数据库的基本操作
    mysql数据库的几个基本概念
    【转载】CentOS6.5_X64下安装配置MongoDB数据库
    Swap Swap,即交换分区
    linux中给PHP安装mongodb的扩展
    centos yum 安装 mongodb 以及php扩展
    设计模式主要分三个类型:创建型、结构型和行为型
    MySQL DELETE语句和TRUNCATE TABLE语句的区别
  • 原文地址:https://www.cnblogs.com/beretty/p/9478704.html
Copyright © 2011-2022 走看看