Codeforces 788D Finding lines 交互题

题意

平面上有若干条水平或竖直的直线。现在每次可以询问某个点到所有直线的最短距离,要求确定所有直线的坐标。
线104||1083105 直 线 数 量 ≤ 10 4 , | 坐 标 | ≤ 10 8 , 询 问 次 数 ≤ 3 ∗ 10 5

分析

先随机出一个数 t t ,满足第 t t 行和第 t t 列都没有直线。
接着设 x=108 x = − 10 8 ,然后逐渐往上跳。
每次查询 (x,x) ( x , x ) ,若当前距离为 0 0 ,则通过查询 (x,t) ( x , t ) (t,x) ( t , x ) 来得到经过 (x,x) ( x , x ) 的是横线还是竖线。
然后把 x+1 x + 1 赋给 x x ,每次从 x x 跳到 x+ask(x,x) x + a s k ( x , x ) ,这样的话距离是倍增的。
但还是太慢了,那么我们考虑让 x x 每次跳 7000 7000 步,如果能跳就跳,不能跳就只跳一步。
就可以过了。

代码

#include
#include
#include
#include
#include

const int N=10005;
const int inf=100000000;

int t,a[N],b[N];

int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int ask(int x,int y)
{
    printf("0 %d %d\n",x,y);
    fflush(stdout);
    return read();
}

int main()
{
    srand(20010104);
    t=rand()*rand()-rand()*rand();
    while (!ask(t,t)) t=rand()*rand()-rand()*rand();
    int x=-inf+ask(-inf,-inf),a1=0,b1=0,step=7000;;
    while (x<=inf)
    {
        if (!ask(x,t)) a[++a1]=x;
        if (!ask(t,x)) b[++b1]=x;
        while (x+step<=inf&&ask(x+step,x+step)>=step) x+=step;
        x++;
        while (x<=inf)
        {
            int d=ask(x,x);
            if (!d) break;
            x+=d;
        }
    }
    printf("%d %d %d\n",1,a1,b1);
    for (int i=1;i<=a1;i++) printf("%d ",a[i]);
    puts("");
    for (int i=1;i<=b1;i++) printf("%d ",b[i]);
    return 0;
}

你可能感兴趣的:(交互题)