zoukankan      html  css  js  c++  java
  • 「HEOI2016/TJOI2016」 排序

    题目链接

    戳我

    (Solution)

    这道题在线的做法不会,所以这里就只讲离线的做法。

    因为直接排序的话复杂度显然不对.但是如果数列为(01)串的话就可以让复杂度变成对的了

    那么(01)串怎么做呢?

    我们考虑用线段树维护这个东西.

    假设我们要将([l,r])排序

    我们可以处理出([l,r])(1)的个数,我们令他为(w)

    如果升序就将([r-x+1,r])设为1,其余为(0)

    如果降序就将([l,l+x-1])设为1,其余为(0)

    那么这个问题怎么变成上述情况呢?

    我们二分最后的答案,令这个数为(mid)

    对于序列中的数,如果小于(mid)就为(0),大于(mid)就为(1)

    然后操作根上述过程一样.

    最后判断下(q)位置是否为(1)

    是,(l=mid+1)

    否,(r=mid-1)

    现在来证明一下这个单调性。

    如果(q)这个位置的数为(1),那么答案肯定为(x+1,x+2,x+3...)所以区间右移,反之亦然。

    (Code)

    #include<bits/stdc++.h>
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    struct node {
    	int lazy,v;
    }a[1000001];
    int c[1000001];
    void pushup(int k){
    	a[k].v=a[k<<1].v+a[k<<1|1].v;
    }
    void build(int k,int l,int r){
    	a[k].lazy=-1,a[k].v=0;
    	if(l==r)
    		return;
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    }
    void pushdown(int k,int l,int r){
    	if(a[k].lazy==-1) return;
    	int mid=(l+r)>>1;
    	a[k<<1].v=(mid-l+1)*a[k].lazy;
    	a[k<<1|1].v=(r-mid)*a[k].lazy;
    	a[k<<1].lazy=a[k<<1|1].lazy=a[k].lazy;
    	a[k].lazy=-1;
    }
    void update(int k,int l,int r,int begin,int end,int v){
    	if(r<begin||l>end) return ;
    	if(r<=end&&l>=begin){
    		a[k].v=(r-l+1)*v;
    		a[k].lazy=v;
    		return ;
    	}
    	pushdown(k,l,r);
    	int mid=(l+r)>>1;
    	update(k<<1,l,mid,begin,end,v);
    	update(k<<1|1,mid+1,r,begin,end,v);
    	pushup(k);
    }
    int find(int k,int l,int r,int begin,int end){
    	if(r<begin&&l>end) return 0;
    	if(r<=end&&l>=begin) return a[k].v;
    	pushdown(k,l,r);
    	int mid=(l+r)>>1;
    	if(end<=mid)
    		return find(k<<1,l,mid,begin,end);
    	else if(begin>mid)
    		return find(k<<1|1,mid+1,r,begin,end);
    	else return find(k<<1,l,mid,begin,mid)+find(k<<1|1,mid+1,r,mid+1,end);
    }
    struct ans{
    	int opt,x,y;
    }b[1000001];
    int n,m,ans,l,r,q;
    bool check(int x){
    	build(1,1,n);
    	for(int i=1;i<=n;i++)
    		update(1,1,n,i,i,c[i]>=x);
    	for(int i=1;i<=m;i++){
    		int opt=b[i].opt,x=b[i].x,y=b[i].y;
    		int w1=find(1,1,n,x,y),w0=y-x+1-w1;
    		if(opt==0)
    			update(1,1,n,x,y,1),update(1,1,n,x,x+w0-1,0);
    		else update(1,1,n,x,y,0),update(1,1,n,x,x+w1-1,1);
    	}
    	return find(1,1,n,q,q)==1;
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++) c[i]=read();
    	for(int i=1;i<=m;i++) b[i].opt=read(),b[i].x=read(),b[i].y=read();
    	l=1,r=n,q=read();
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(check(mid)) l=mid+1,ans=mid;
    		else r=mid-1;
    	}
    	printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    newCachedThreadPool无上限线程池使用
    newFixedThreadPool固定线程使用
    java定时器
    http文件上传/下载
    ThreadPoolExecutor线程池
    阻塞队列
    非阻塞队列
    IO文件夹拷贝(文件内含有文件和文件夹)
    MD5加密
    web.xml文件的作用
  • 原文地址:https://www.cnblogs.com/hbxblog/p/11708862.html
Copyright © 2011-2022 走看看