• 2019.2.14 考试T3 交互题


    (color{#0066ff}{ 题目描述 })

    由于机房被成功拯救了,花_Q很高兴,花_Q生成了一个 0 到 N - 1 的排列(排列的下标从 0 到 N - 1 )。保证排列中 0 在 N - 1 的左边。
    lzxkj一向很好奇,他想要知道这个排列是什么,但是由于lzxkj和阿习小pen友一起来的,的花_Q就是不告诉他。
    阿习小pen友很聪明,Ta每次向花_Q询问一个区间 [l, r] ,花_Q 会告诉Ta区间 [l, r] 内的最大值减去最小值的值(极差)。阿习小朋友在不超过 10000 次询问后就从花_Q那里得到他的区间了。 lzxkj 很满意 假如你是阿习,你能还原出这个排列吗?
    你需要在不超过10000次询问之内还原这个排列。


    你不需要也不应该实现主函数,你需要实现如下函数:

    get_permutation(N, ans)

    其中 N 代表排列的长度,你需要将计算出来的答案保存在 ans 数组中, ans[i] 代表第 i 个位置的排列的值。

    你可以调用 query(l, r) 来询问区间 [l, r] 的内的极差。你需要保证 0 <= l <= r <= N - 1 。

    调用一次 query 函数的复杂度为 O(r - l + 1) 。


    你需要提交一个源文件 permutation.cpp 并实现上述函数,并且遵循下面的命名和接口。

    你的源代码中需要包含头文件 permutation.h 。

    你需要实现的函数 get_permutation 定义如下:

    void get_permutation(int N, int ans[]);

    函数 query 的接口如下:

    int query(int l, int r);


    你需要在目录下使用如下命令编译得到可执行程序:

    g++ grader.cpp permutation.cpp -o permutation -O2 -lm

    可执行文件从标准输入读入以下格式的数据:

    第一行包含一个整数N。需要保证N在 [1, 5000] 之间。

    第二行包含 N 个 0 ~ N - 1 之间的正整数,表示 0 ~ N - 1 的排列。

    你的输入要保证是一个排列。

    读入完成后,交互库将会调用 get_permutation 函数。如果此时你调用 query 函数的次数超过 10000 次,则交互库会输出错误信息并退出。

    当你的函数返回后,交互库会判断 ans 数组里的答案是否正确。如果正确则会输出 "Correct" ,否则会输出错误信息。


    最终评测时只收取 permutation.cpp 。题目首先会受到和非交互式程序题相同的限制。例如编译错误会导致整道题目得 0 分,运行时错误、超过时间限制、超过空间限制等会导致相应测试点得 0 分等。你只能访问自己定义的和交互库给出的变量及其对应的内存空间,尝试访问其他空间将可能导致编译错误或运行错误。

    在上述条件基础上,在一个测试点中,你得到满分,当且仅当你的每次调用都合法,并且最终返回的结果正确。

    题目中所给的时间、空间限制为你的代码和交互库加起来可以使用的时间和空间。我们保证,对于任何合法的数据及在限制范围内的调用,交互库运行所用的时间不会超过 1s ,运行所占内存不会超过 128M ,也就是说,选手实际可用的时间至少为 1s ,实际可用内存至少为 384M 。

    (color{#0066ff}{输入格式})

    函数传参

    (color{#0066ff}{输出格式})

    将输出存入ans数组内

    (color{#0066ff}{输入样例})

    5
    0 3 2 4 1
    

    (color{#0066ff}{输出样例})

    Correct
    

    (color{#0066ff}{数据范围与提示})

    一共有 20 个测试点,每个测试点 5 分。

    对于 30% 的数据,有 N <= 100 。

    对于 60% 的数据,有 N <= 1000 。

    对于 100% 的数据,有 N <= 5000 。

    (color{#0066ff}{ 题解 })

    首先,钦定0为第一个

    然后询问(0,1),钦定第二个为刚刚询问的ans

    从第三个数开始,每次询问(i-2,i)和(i-1,i),记为a,b

    到底是上一个数+b还是-b,讨论a是由这三个数中的哪两个数取得的,就可以唯一确定

    最后的序列值域可能不是[0,n-1],同时减去最小值变回来

    还有,0必须在n-1的左边,如果在右边,就让所有数变为(n-1-当前数),这样,差不变,0和n-1反向

    就没了

    #include"permutation.h"
    #include<cstdio>
    #include<iostream>
    
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 5010;
    bool flag;
    int n;
    int abs(int x) { return x > 0? x : -x; }
    void get_permutation(int N, int ans[]) {
    	ans[0] = 0;
    	ans[1] = query(0, 1);
    	for(int i = 2; i < N; i++) {
    		int t1 = query(i - 2, i);
    		int t2 = query(i - 1, i);
    		int a = ans[i - 1] + t2;
    		int b = ans[i - 1] - t2;
    		if(t1 == abs(ans[i - 1] - ans[i - 2])) {
    			if(a >= std::min(ans[i - 1], ans[i - 2]) && a <= std::max(ans[i - 1], ans[i - 2])) ans[i] = a;
    			else ans[i] = b;
    		}
    		else if(t1 == t2) {
    			if(ans[i - 1] > ans[i - 2]) ans[i] = b;
    			else ans[i] - a;
    		}
    		else {
    			if(ans[i - 1] > ans[i - 2]) ans[i] = a;
    			else ans[i] = b;
    		}
    	}
    	int min = 0x7fffffff;
    	for(int i = 0; i < N; i++) min = std::min(min, ans[i]);
    	for(int i = 0; i < N; i++) ans[i] -= min;
    	int pos0, posn;
    	for(int i = 0; i < N; i++) {
    		if(ans[i] == 0) pos0 = i;
    		if(ans[i] == N - 1) posn = i;
    	}
    	if(pos0 > posn) for(int i = 0; i < N; i++) ans[i] = N - 1 - ans[i];
    }
    
  • 相关阅读:
    topcoder srm 708 div1
    FBX SDK在vs 2010下面的配置
    Google Protocol Buffer在vs2010下配置
    topcoder srm 709 div1
    topcoder srm 707 div1
    CNN Mnist
    SVM学习笔记5-SMO
    SVM学习笔记4-核函数和离群点的处理
    SVM学习笔记3-问题转化
    如何使用SSL pinning来使你的iOS APP更加安全
  • 原文地址:https://www.cnblogs.com/olinr/p/10374973.html
Copyright © 2020-2023  润新知