zoukankan      html  css  js  c++  java
  • 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
     
    特派员好gin啊,竟然直接出鏼爷BC的题(竟然连样例都没改)
    直接处理很难做,我们发现可以二分答案,这样对于01序列我们是很方便排序的,用棵线段树随便搞搞就行了。
    时间复杂度为O(Mlog^2N)
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int n,m,k,A[maxn];
    int setv[maxn<<2],sumv[maxn<<2];
    void maintain(int o,int l,int r) {
    	if(setv[o]>=0) sumv[o]=(r-l+1)*setv[o];
    	else sumv[o]=sumv[o<<1]+sumv[(o<<1)|1];
    }
    void pushdown(int o) {
    	if(setv[o]>=0) {
    		int lc=o<<1,rc=lc|1;
    		setv[lc]=setv[rc]=setv[o];
    		setv[o]=-1;
    	}
    }
    void build(int o,int l,int r,int x) {
    	if(l==r) setv[o]=(A[l]<=x);
    	else {
    		setv[o]=-1;
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		build(lc,l,mid,x);build(rc,mid+1,r,x);
    	}
    	maintain(o,l,r);
    }
    void update(int o,int l,int r,int ql,int qr,int val) {
    	if(ql<=l&&r<=qr) setv[o]=val;
    	else {
    		pushdown(o);
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		if(ql<=mid) update(lc,l,mid,ql,qr,val);
    		else maintain(lc,l,mid);
    		if(qr>mid) update(rc,mid+1,r,ql,qr,val);
    		else maintain(rc,mid+1,r);
    	}
    	maintain(o,l,r);
    }
    int query(int o,int l,int r,int ql,int qr) {
    	if(setv[o]>=0) return setv[o]*(min(qr,r)-max(ql,l)+1);
    	if(ql<=l&&r<=qr) return sumv[o];
    	int mid=l+r>>1,lc=o<<1,rc=lc|1,ans=0;
    	if(ql<=mid) ans+=query(lc,l,mid,ql,qr);
    	if(qr>mid) ans+=query(rc,mid+1,r,ql,qr);
    	return ans;
    }
    int ty[maxn],ql[maxn],qr[maxn];
    int check(int x) {
    	build(1,1,n,x);
    	rep(i,1,m) {
    		int res=query(1,1,n,ql[i],qr[i]);
    		if(!res||res==qr[i]-ql[i]+1) continue;
    		if(ty[i]) {
    			update(1,1,n,ql[i],qr[i]-res,0);
    			update(1,1,n,qr[i]-res+1,qr[i],1);
    		}
    		else {
    			update(1,1,n,ql[i],ql[i]+res-1,1);
    			update(1,1,n,ql[i]+res,qr[i],0);
    		}
    	}
    	return query(1,1,n,k,k);
    }
    int main() {
    	n=read();m=read();
    	rep(i,1,n) A[i]=read();
    	rep(i,1,m) ty[i]=read(),ql[i]=read(),qr[i]=read();
    	k=read();
    	int l=1,r=n,mid;
    	while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
    	printf("%d
    ",l);
    	return 0;
    }
    

      

  • 相关阅读:
    【数据结构】堆栈
    【数据结构】线性表
    【算法】最大子列和问题
    【算法】复杂度的渐近表示
    【算法】什么是好的算法
    【算法】什么是算法
    【数据结构】什么是数据结构
    MySQL数据备份脚本
    二进制安装MySQL-5.7.28
    搭建zabbix+grafana监控
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5505216.html
Copyright © 2011-2022 走看看