CF_Round274_Div1_B_Long Jump_二分搜索

突然发现区域赛好难。。。。再不好好训练就要打铁了。。。。。。。


题意:

给正整数x和y,还有一个长度为n的数组,其中最小为0,最大为L,没有相同的值,问最少添加多少个在0到L之间的数,使得数组满足对x, y均存在i, j,a[i]-a[j]和其相等。



Input

The first line contains four positive space-separated integers n, l, x, y (2 ≤ n ≤ 105,2 ≤ l ≤ 109,1 ≤ x < y ≤ l) — the number of marks, the length of the ruler and the jump norms for girls and boys, correspondingly.

The second line contains a sequence of n integersa1, a2, ..., an (0 = a1 < a2 < ... < an = l), where ai shows the distance from thei-th mark to the origin.

Output

In the first line print a single non-negative integer v — the minimum number of marks that you need to add on the ruler.

In the second line print v space-separated integersp1, p2, ..., pv (0 ≤ pi ≤ l). Number pi means that thei-th mark should be at the distance of pi centimeters from the origin. Print the marks in any order. If there are multiple solutions, print any of them.

思路不难,先对x,遍历a数组中的每个数,找a[i]+x和a[i]-x是否在数组中,不再数组中的数加入另一个数组ans,一旦找到一个值在数组中,就break,ans数组也没意义了。之后对y,同样遍历a中每个数,找a[i]+y和a[i]-y是否在a中,不在并且x也找不到时,在ans中找这个值,一旦找到就说明x和y共用这个添加点,否则各自计算。

比赛的时候因为一些小地方WA了四发,最后还RE了,现在还没提交,应该是ans数组开小了。

代码写的比较乱。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
#define mxn 100010
int a[mxn];
int n,l,x,y;
int ans[mxn<<2],cnt;
int bin(int tgt,int s[],int mx){
    int l=0,r=mx,m;
    while(l+1<r){
        m=(l+r)>>1;
        if(s[m]<=tgt)   l=m;
        else    r=m;
    }
    if(s[l]!=tgt)   return -1;
    return l;
}
int rec[2];
bool nd[2];
int main(){
    while(scanf("%d%d%d%d",&n,&l,&x,&y)!=EOF){
        for(int i=0;i<n;++i)    scanf("%d",&a[i]);
        cnt=0;
        for(int i=0;i<n;++i){
            int tem=a[i]-x;
            int loc;
            if(tem>=0){
                loc=bin(tem,a,n);
                if(loc==-1){
                    nd[0]=true;
                    rec[0]=tem;
                    ans[cnt++]=tem;
                }
                else{
                    nd[0]=false;
                    break;
                }
            }

            tem=a[i]+x;
            if(tem>l)   continue;
            loc=bin(tem,a,n);
            if(loc==-1){
                nd[0]=true;
                rec[0]=tem;
                ans[cnt++]=tem;
            }
            else{
                nd[0]=false;
                break;
            }
        }
        sort(ans,ans+cnt);
        for(int i=0;i<n;++i){
            int tem=a[i]-y;
            int loc;
            if(tem>=0){
            loc=bin(tem,a,n);
            if(loc!=-1){
                nd[1]=false;
                break;
            }
            else if(nd[0]){
                loc=bin(tem,ans,cnt);
                if(loc!=-1){
                    nd[1]=false;
                    rec[0]=tem;
                    break;
                }
                else{
                    nd[1]=true;
                    rec[1]=tem;
                }
            }
            else{
                nd[1]=true;
                rec[1]=tem;
            }
            }

            tem=a[i]+y;
            if(tem>l)   continue;
            loc=bin(tem,a,n);
            if(loc!=-1){
                nd[1]=false;
                break;
            }
            else if(nd[0]){
                loc=bin(tem,ans,cnt);
                if(loc!=-1){
                    nd[1]=false;
                    rec[0]=tem;
                    break;
                }
                else{
                    nd[1]=true;
                    rec[1]=tem;
                }
            }
            else{
                nd[1]=true;
                rec[1]=tem;
            }
        }
        if(nd[0]&&nd[1]){
            puts("2");
            printf("%d %d\n",rec[0],rec[1]);
        }
        else if(nd[0]){
            puts("1");
            printf("%d\n",rec[0]);
        }
        else if(nd[1]){
            puts("1");
            printf("%d\n",rec[1]);
        }
        else    puts("0");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值