noi.ac NOIP2018 全国热身赛 第四场 T2 sort

【题解】

  跟51nod 1105差不多。

  二分答案求出第L个数和第R个数,check的时候再套一个二分或者用two pointers.

  最后枚举ai在b里面二分,找到所有范围内的数,排序后输出。

  注意最后找到的数可能多于R-L+1,需要考虑这一点。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #define LL long long
 6 #define rg register
 7 #define N 100010
 8 using namespace std;
 9 LL tot,n,l,r,st,ed,mn,mx,a[N],b[N],ans[N];
10 inline LL read(){
11     LL k=0,f=1; char c=getchar();
12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
14     return k*f;
15 } 
16 inline LL check(LL x){
17     LL sum=0;
18     for(rg int i=1;i<=n;i++){
19         LL tmp=x-a[i]+1;
20         sum+=lower_bound(b+1,b+1+n,tmp)-b-1;
21 //        printf("sum=%d\n",sum);
22     }
23 //    printf("sum=%d\n",sum);
24     return sum;
25 }
26 int main(){
27     n=read(); st=read(); ed=read();
28     for(rg int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+1+n); 
29     for(rg int i=1;i<=n;i++) b[i]=read(); sort(b+1,b+1+n);
30     l=a[1]+b[1]-1; r=a[n]+b[n];
31     while(l+1<r){
32         LL mid=(l+r)>>1;
33         if(check(mid)>=st) r=mid; else l=mid;
34     }
35     mn=r;
36     l=a[1]+b[1]-1; r=a[n]+b[n];
37     while(l+1<r){
38         LL mid=(l+r)>>1;
39         if(check(mid)>=ed) r=mid; else l=mid;
40     }
41     mx=r;
42 //    printf("%d %d\n",mn,mx);
43     for(rg int i=1;i<=n;i++){
44         int tmp=mn-a[i],tmp2=mx-a[i];
45         int pos1=lower_bound(b+1,b+1+n,tmp)-b;
46         if(pos1==n+1) continue;
47         int pos2=upper_bound(b+1,b+1+n,tmp2)-b;
48 //        printf("%d %d\n",pos1,pos2);
49         for(rg int j=pos1;j<pos2;j++) ans[++tot]=a[i]+b[j];
50     }
51     sort(ans+1,ans+1+tot);
52     tot=min(tot,ed-st+1);
53     for(rg int i=1;i<=tot;i++) printf("%lld ",ans[i]);
54     return 0;
55 }

 

posted @ 2018-10-28 20:18  Driver_Lao  阅读(385)  评论(1编辑  收藏  举报