Codeforces 479D - Long Jumps

479D - Long Jumps, 480B - Long Jumps
It is easy to see that the answer is always 0, 1 or 2. If we can already measure both x and y, output 0. Then try to measure both x and y by adding one more mark. If it was not successful, print two marks: one at x, other at y.

So, how to check if the answer is 1? Consider all existing marks. Let some mark be at r. Try to add the new mark in each of the following positions: r - x, r + x, r - y, r + y. If it become possible to measure both x and y, you have found the answer. It is easy to check this: if, for example, we are trying to add the mark at r + x, we just check if there is a mark at r + x + y or r + x - y (by a binary search, since the marks are sorted). Make sure that the adde marks are in [0, L].

好久没写解题报告了。

这是一道模拟题,其实是看了Tutorial 才确定下的算法思路。

题目意思还是很简单的,在[0, L]范围内增加一个标记处,使得能测量出X,Y的值。

易得,增加标记出只有三种情况,0,1,2

0的话就是已有的标记出就可以测量出X,Y的值。

2的话就是 就算增加一个标记出也无法测量出X,Y的值。

在1这种情况下是可以分类的。

1.r -c

2.r + c

3.r - y

4.r + y

有四种可能标记处。

ex. 如果我们在(r + c)处做标记(保证合法),则判断原有序列中是否存在(r + c) - y 或者是(r + c) + y

如果存在,则得证增加这么一个(r + c)可以测量出X,Y的值。

如果还不动,画一条先端模拟一下就会懂了~

 

Tips: 有一点不能忘记,就是一开始算已有的标记出是否能测出X,Y的时候

不能用O(n^2)的遍历。

只需要O(n)的遍历,当然,同一数字可能同时满足测量X,Y的情况。

(查找一个值的时候,在有序序列中可用STL中的binary_search)

 

好久没贴代码了= = 

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
using namespace std;
const int INF = 0x3f3f3f3f;

int a[100001];
int n, l;

bool Ok(int num){
    if(num > 0 && num <= l) return true;
    return false;
}

int main(){
    int i, j, k, t, x, y;
    while(EOF != scanf("%d%d%d%d",&n,&l,&x,&y)){
        for(i = 1; i <= n; ++i) scanf("%d",&a[i]);
        bool xx = false;
        bool yy = false;
        for(i = 1; i <= n; ++i){
            if(binary_search(a, a + n + 1, a[i] + x)){
                xx = true;
            }
            if(binary_search(a, a + n + 1, a[i] + y)){
                yy = true;
            }
        }
        if(xx && yy){
            printf("0\n");
            continue;
        }
        bool status = false;
        for(i = 1; i <= n; ++i){
            if(Ok(a[i] - x)){
                if(yy){
                    printf("1\n%d\n",a[i] - x);
                    status = true;
                    break;
                }
                if(binary_search(a, a + n + 1, a[i] - x - y) || binary_search(a, a + n + 1, a[i] - x + y)){
                    printf("1\n%d\n",a[i] - x);
                    status = true;
                    break;
                }
            }
            if(Ok(a[i] + x)){
                if(yy){
                    printf("1\n%d\n",a[i] + x);
                    status = true;
                    break;
                }
                if(binary_search(a, a + n + 1, a[i] + x - y) || binary_search(a, a + n + 1, a[i] + x + y)){
                    printf("1\n%d\n",a[i] + x);
                    status = true;
                    break;
                }
            }
            if(Ok(a[i] - y)){
                if(xx){
                    printf("1\n%d\n",a[i] - y);
                    status = true;
                    break;
                }
                if(binary_search(a, a + n + 1, a[i] - y - x) || binary_search(a, a + n + 1, a[i] - y - x)){
                    printf("1\n%d\n",a[i] - y);
                    status = true;
                    break;
                }
            }
            if(Ok(a[i] + y)){
                if(xx){
                    printf("1\n%d\n",a[i] + y);
                    status = true;
                    break;
                }
                if(binary_search(a, a + n + 1, a[i] + y - x) || binary_search(a, a + n + 1, a[i] + y + x)){
                    printf("1\n%d\n",a[i] + y);
                    status = true;
                    break;
                }
            }
        }
        if(!status){
            printf("2\n%d %d\n",x,y);
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/wushuaiyi/p/4052503.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值