zoukankan      html  css  js  c++  java
  • 2020 ICPC North America Championship Problem G

    Problem Link

    statement

    有数组A与数组B,你可以选择A的某个数与B的某个数搭配,每次搭配需要满足数组中每个数不重复选且(a_i+b_ileq s),令(d_i=abs(a_i-b_i)),(D=max(d_1,d_2,..,d_n)),求完成n组匹配能得到的最小的D。

    input

    (nleq 2 imes 10^5)
    (a_i,b_i,sleq 10^9)

    idea

    啊,这题竟然比赛时没做出来quq...实在没想到怎么贪。
    首先看到D是一堆数的最大,又要求D的最小,最大的最小与最小的最大很明显是二分答案的信号。我们二分每个D,对于数组A每个数x对应的B数组的数y需要满足

    egin{cases} &yleq s-x\ &yleq D+x\ &ygeq x-d end{cases}

    我们将A,B数组排序,按照以上不等式,每个A数组对应可选的B数组为一段序列,我们将以上序列排序后从左到右枚举B数组每个数。首先,如果当前的数在一段序列内,一定要拿,因为每次匹配都是相同的贡献,你留着不拿,给后面的数拿并不会增加贡献。其次,如果有多个序列段能进行匹配,一定要拿r(序列右端点)最小的,因为后面的数l一定比当前数大,所以l不能产生约束,但是当前拿r最小的,可能可以给后面更多的数得到匹配。所以就这么贪心地拿,在$O(nlog n)$内可以完成匹配。而二分答案次数为$O(log s)$,故总时间复杂度为$O(nlog nlog s)$。

    代码

    /*************************************************************************
    	> File Name: 3.cpp
    	> Author: Knowledge_llz
    	> Mail: 925538513@qq.com 
    	> Blog: https://blog.csdn.net/Pig_cfbsl 
    	> Created Time: 2020/10/5 14:20:58
     ************************************************************************/
    #include<bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define pb push_back
    #define pr pair<int,int>
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define LL long long
    using namespace std;
    int read(){
    	char x=getchar(); int u=0,fg=0;
    	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
    	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
    	return fg?-u:u;
    }
    const int maxx=2e5+10;
    int a[maxx],b[maxx],n,p,q,s;
    struct cmp{
    	bool operator () (const pr &a,const pr &b)const{
    		return a.se>b.se;
    	}
    };
    queue<pr>Q;
    priority_queue<pr,vector<pr>,cmp>que;
    bool check(int d){
    	int tmp=0;
    	while(!Q.empty()) Q.pop();
    	while(!que.empty()) que.pop();
    	For(i,1,p){
    		int x=lower_bound(b+1,b+q+1,a[i]-d)-b,lim=min(a[i]+d,s-a[i]);
    		int y=upper_bound(b+1,b+q+1,lim)-b-1;
    		if(x<=y) Q.push(mk(x,y));
    	}
    	For(i,1,q){
    		while(!Q.empty() && Q.front().fi<=i){
    			que.push(Q.front());
    			Q.pop();
    		}
    		while(!que.empty()){
    			int r=que.top().se;
    			que.pop();
    			if(r<i)	continue; 
    			++tmp;
    			break;
    		}
    		if(tmp>=n) return tmp>=n;
    	}
    	return tmp>=n;
    }
    		
    int main()
    {
    //	freopen("input.in","r",stdin);
    //	freopen("output.out","w",stdout);
    	n=read(); p=read(); q=read(); s=read();
    	For(i,1,p) a[i]=read();
    	For(i,1,q) b[i]=read();
    	sort(a+1,a+p+1);
    	sort(b+1,b+q+1);
    	int l=0,r=1e9,mid,ans=-1;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(check(mid)){ r=mid-1; ans=mid; }
    		else l=mid+1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    request.getParameter() 、 request.getInputStream()和request.getReader() 使用体会
    HTTP之Content-Length
    关于spring3中No Session found for current thread!and Transaction的配置和管理(转)
    Java数据类型和MySql数据类型对应一览
    Spring MVC 解读——View,ViewResolver(转)
    LeetCode 441. Arranging Coins
    LeetCode 415. Add Strings
    LeetCode 400. Nth Digit
    LeetCode 367. Valid Perfect Square
    LeetCode 326. Power of Three
  • 原文地址:https://www.cnblogs.com/Knowledge-Pig/p/13772043.html
Copyright © 2011-2022 走看看