zoukankan      html  css  js  c++  java
  • uoj#280. 【UTR #2】题目难度提升(构造)

    传送门

    咱先膜一下(GXZ)再说

    我们先把序列从小到大排序,然后分情况讨论

    无解是不存在的,从小到大输出所有数肯定可行

    情况一,如果(a[mid]=a[mid+1]),因为最终的中位数也是它们,那么我们可以让中位数一直等于(a[mid]),找到最大的(k)满足(a[k]=a[mid]),那么就先删(k),然后再删(k-1,n,k-2,n-1,...)那么显然这个过程中中位数始终为(a[mid]),且满足字典序最大

    情况二,如果(a[mid] eq a[mid+1])且存在(k<lceilfrac n2 ceil,a_k=a_{k+1}),那么我们可以从(k)开始取,然后按(k-1,n,k-2,n-1,...)的顺序取,最后前面的数一定会被取完,而且这个过程中中位数不变

    情况三,第一个数只能取(a[1]),因为很明显删数的过程中要始终满足删的数不能小于已删的数的中位数否则(GG)

    于是维护一个叫做对顶堆的东西,简单来说就是把小的数放一个大根堆里,大的数放一个小根堆里,并保证两堆的元素个数之差不超过(1),那么中位数只要从两个堆顶取就行了

    对于剩下的所有未删除的数,因为按照我们上面的做法,情况一是已经做完了,情况二和情况三都会删到只剩一个连续的区间,且这个区间的中位数大于等于已经删的数的中位数,于是每一次加入能使中位数大于等于剩下的最小的数的就行了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define IT set<int>::iterator
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    }
    const int N=1e5+5;
    multiset<int>s;priority_queue<int>A,B;
    int a[N],vis[N],n;
    void push(int x){
    	if(A.empty()||x<=A.top())A.push(x);
    	else B.push(-x);
    	if(A.size()<B.size())A.push(-B.top()),B.pop();
    	if(A.size()-B.size()>1)B.push(-A.top()),A.pop();
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	fp(i,1,n)a[i]=read();
    	sort(a+1,a+1+n);
    	int mid=(n+1)>>1;
    	if(a[mid]==a[mid+1]){
    		while(mid<n&&a[mid]==a[mid+1])++mid;
    		print(a[mid]);
    		int p=mid-1,q=n;
    		while(p||q>mid){
    //			printf("%d %d
    ",p,q);
    			if(p)print(a[p--]);
    			if(q>mid)print(a[q--]);
    		}return Ot(),0;
    	}
    	while(mid>1&&a[mid]!=a[mid-1])--mid;
    	print(a[mid]),vis[mid]=1;
    	int p=mid-1,q=n;IT it;
    	while(p&&q>mid)print(a[p]),print(a[q]),vis[p--]=vis[q--]=1;
    	fp(i,1,n)if(vis[i])push(a[i]);else s.insert(a[i]);
    	while(!s.empty()){
    		p=*s.begin();
    		if(A.size()==B.size())it=(p>=-B.top())?--s.end():s.begin();
    		else{
    			if(!B.empty()&&p*2>=A.top()-B.top())it=--s.end();
    			else it=--s.upper_bound(p*2-A.top());
    		}
    		print(*it),push(*it),s.erase(it);
    	}
    	return Ot(),0;
    }
    
  • 相关阅读:
    Visual Studio Code必备插件
    webpack4+:. css属性自动追加前缀 与 mini-css-extract-plugin 插件 打包冲突问题
    webpack4.x抽取css【extract-text-webpack-plugin与mini-css-extract-plugin】
    javaScript中slice, substring,substr三者区别以及用法扩展
    Spring Boot实践——Mybatis分页插件PageHelper的使用
    Nginx配置详解
    Maven的几个常用plugin
    excel拼接数据宏
    我的Linux之路——windows10用WMware安装CentOS7.5 虚拟机详细步骤
    Spring Boot实践——多线程
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10287667.html
Copyright © 2011-2022 走看看