zoukankan      html  css  js  c++  java
  • BZOJ4552: [Tjoi2016&Heoi2016]排序

    BZOJ4552: [Tjoi2016&Heoi2016]排序

    Description

    在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
    ,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
    序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
    位置上的数字。

    Input

    输入数据的第一行为两个整数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

    Output

     输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

    Sample Input

    6 3
    1 6 2 5 3 4
    0 1 4
    1 3 6
    0 2 4
    3

    Sample Output

    5

    题解Here!

    首先,这道题只有一组查询,所以可以二分这个数的排名。

    每次二分一个要查询的数在序列中的大小排名(排名指在升序的情况下的排名)。

    然后我们原数列进行一些变形:

    当$val[i] >= mid$时,此位置就为$1$,反之则为$0$。

    这样一来,这道题就变成了一个$01$序列排序,所以就可以用线段树实现$log_2n$排序。

    线段树维护区间和,需要实现区间覆盖。

    每次排序前先查询排序一共有多少$1$。

    升序排序则将$left[r- ext{区间1的数量}+1,r ight]$改为$1$,$left[l,r- ext{区间1的数量} ight]$改为$0$

    最后再查询要询问的位置。

    若要查询的位置为$1$,那么就增加其排名,即$r=mid-1$

    反之,就降低这个数排名。

    由于这个数列是$left[1,n ight]$的全排列,所以二分出的结果就是答案。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) a[x].data
    #define SIGN(x) a[x].c
    #define LSIDE(x) a[x].l
    #define RSIDE(x) a[x].r
    #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
    #define MAXN 100010
    using namespace std;
    int n,m,q;
    int val[MAXN],num[MAXN];
    struct Segment_Tree{
    	int data,c;
    	int l,r;
    }a[MAXN<<2];
    struct Question{
    	int f,l,r;
    }que[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void pushup(int rt){
    	DATA(rt)=DATA(LSON)+DATA(RSON);
    }
    inline void pushdown(int rt){
    	if(SIGN(rt)==-1||LSIDE(rt)==RSIDE(rt))return;
    	SIGN(LSON)=SIGN(rt);
    	DATA(LSON)=SIGN(rt)*WIDTH(LSON);
    	SIGN(RSON)=SIGN(rt);
    	DATA(RSON)=SIGN(rt)*WIDTH(RSON);
    	SIGN(rt)=-1;
    }
    void buildtree(int l,int r,int rt){
    	LSIDE(rt)=l;RSIDE(rt)=r;SIGN(rt)=-1;
    	if(l==r){
    		DATA(rt)=num[l];
    		return;
    	}
    	int mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    	pushup(rt);
    }
    void update(int l,int r,int c,int rt){
    	if(l>r)return;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		SIGN(rt)=c;
    		DATA(rt)=c*WIDTH(rt);
    		return;
    	}
    	pushdown(rt);
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update(l,r,c,LSON);
    	if(mid<r)update(l,r,c,RSON);
    	pushup(rt);
    }
    int query(int l,int r,int rt){
    	if(l>r)return 0;
    	int ans=0;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
    	pushdown(rt);
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans+=query(l,r,LSON);
    	if(mid<r)ans+=query(l,r,RSON);
    	return ans;
    }
    bool check(int mid){
    	for(int i=1;i<=n;i++)num[i]=(val[i]>=mid?1:0);
    	buildtree(1,n,1);
    	for(int i=1;i<=m;i++){
    		int l=que[i].l,r=que[i].r;
    		if(que[i].f==0){
    			int k=query(l,r,1);
    			update(r-k+1,r,1,1);update(l,r-k,0,1);
    		}
    		else{
    			int k=query(l,r,1);
    			update(l,l+k-1,1,1);update(l+k,r,0,1);
    		}
    	}
    	return query(q,q,1);
    }
    void work(){
    	int l=1,r=n,mid,ans=0;
    	while(l<=r){
    		mid=l+r>>1;
    		if(check(mid)){ans=mid;l=mid+1;}
    		else r=mid-1;
    	}
    	printf("%d
    ",ans);
    }
    void init(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++)val[i]=read();
    	for(int i=1;i<=m;i++){que[i].f=read();que[i].l=read();que[i].r=read();}
    	q=read();
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    IDEA15 下运行Scala遇到问题以及解决办法
    关于Solr6.0中solrj使用简单例子
    How to Reuse Old PCs for Solr Search Platform?
    Build IKAnalyzer With Solr 5.1.0
    ZooKeeper(3.4.5)
    Android OpenGL ES(四)关于EGL .
    Android OpenGL ES(三)OpenGL ES API 命名习惯 .
    Android OpenGL ES(二)OpenGL ES管道(Pipeline) .
    Android OpenGL ES(一)OpenGL ES介绍
    Android OpenGL 入门示例----绘制三角形和正方形
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9531359.html
Copyright © 2011-2022 走看看