#52. 【UR #4】元旦激光炮 (交互式题)

链接:http://uoj.ac/problem/52

刚刚越过绝境长城,只见天空中出现了炫目的光芒 —— 圣诞老人出现了。

元旦三侠立刻进入战斗。生蛋侠、圆蛋侠和零蛋侠分别有 na,nb,ncna,nb,nc 个激光炮。生蛋侠的激光炮的威力分别为 a0,a1,…,ana−1a0,a1,…,ana−1,圆蛋侠的激光炮的威力分别为 b0,b1,…,bnb−1b0,b1,…,bnb−1,零蛋侠的激光炮的威力分别为 c0,c1,…,cnc−1c0,c1,…,cnc−1。

元旦三侠的激光炮的威力已经按从小到大的顺序排好序了,即 ai−1≤aiai−1≤ai,bi−1≤bibi−1≤bi,ci−1≤cici−1≤ci。

由于元旦三侠精力有限,他们得废弃掉 kk 个激光炮。为了更好地进行战斗,他们决定废弃掉威力前 kk 小的激光炮。

赶快帮助元旦三侠,让激光炮投入战斗吧!你只需要告诉他们威力第 kk 小的激光炮威力是多少。

任务
你需要编写一个函数 query_kth,以确定威力值第 kk 小的激光炮威力值是多少。

query_kth(n_a, n_b, n_c, k)
n_a:生蛋侠拥有的激光炮数目 nana。保证 na≥0na≥0。
n_b:圆蛋侠拥有的激光炮数目 nbnb。保证 nb≥0nb≥0。
n_c:零蛋侠拥有的激光炮数目 ncnc。保证 nc≥0nc≥0。
kk:要查询的排名 kk。保证 1≤k≤na+nb+nc1≤k≤na+nb+nc。
你可以调用三个函数 get_a、get_b、get_c 以帮助你确定第 kk 小的激光炮。我们会根据你调用这三个函数的总次数评分。

get_a(i) 将返回 aiai。如果 ii 在 0≤i<na0≤i<na 之外,该函数将返回 21474836472147483647。
get_b(i) 将返回 bibi。如果 ii 在 0≤i<nb0≤i<nb 之外,该函数将返回 21474836472147483647。
get_c(i) 将返回 cici。如果 ii 在 0≤i<nc0≤i<nc 之外,该函数将返回 21474836472147483647。
在一组测试数据中,query_kth 只会被调用一次。

实现细节
本题只支持 C/C++/Pascal。

你只能提交一个源文件实现如上所述的 query_kth 函数,并且遵循下面的命名和接口。

C/C++

你需要包含头文件 kth.h。

int query_kth(int n_a, int n_b, int n_c, int k);
函数 get_a, get_b, get_c 的接口信息如下。

int get_a(int p);
int get_b(int p);
int get_c(int p);
Pascal

你需要使用单元 graderhelperlib。

function query_kth(n_a, n_b, n_c, k : longint) : longint;
函数 get_a, get_b, get_c 的接口信息如下。

function get_a(p : longint) : longint;
function get_b(p : longint) : longint;
function get_c(p : longint) : longint;
如果有不清楚的地方,见样例及测评库下载,内附了样例程序。

评测方式
评测系统将读入如下格式的输入数据:

第 11 行: na,nb,nc,kna,nb,nc,k
第 22 行:nana 个整数,第 ii 个整数表示 aiai。
第 33 行:nbnb 个整数,第 ii 个整数表示 bibi。
第 44 行:ncnc 个整数,第 ii 个整数表示 cici。
在 query_k 返回后,评测系统将输出你的答案以及 get_a, get_b, get_c 三个函数的总调用次数。

样例一
input

2 3 3 5
1 2
1 5 6
2 3 3

output

3 6

explanation

所有激光炮从小到大排序后为 1,1,2,2,3,3,5,61,1,2,2,3,3,5,6,所以第 55 小的数为 33。输出的第二个整数 66 为总调用次数,你可以认为这是一个调用了 66 次 get_a, get_b, get_c 函数的程序的输出。

样例二
见样例及测评库下载。

限制与约定
共 1010 个测试点,每个测试点 1010 分。设你的程序 get_a, get_b, get_c 函数的调用次数为 tt。当 t≤100t≤100 时得 1010 分,否则当 t≤2000t≤2000 时得 66 分,否则不得分。

测试点编号    特殊限制
1    na,nb,nc≤30na,nb,nc≤30
2    nc=0nc=0
3
4
56
7
8
9
10
对于所有测试点,0≤na,nb,nc≤1050≤na,nb,nc≤1051≤ai,bi,ci≤1091≤ai,bi,ci≤109。

交互式类型的题目怎么本地测试

时间限制:1s1s
空间限制:256MB
题干

第一次接触交互式的题目,挺费事的,但还挺有趣的。

思路:

  如果你一个一个读取就超时了,但如果我读每组数的第k/3个,可以保证的是最小的那一列肯定在所有数的前K小。这句话是关键。

  然后k就减小k/3,重复以上操作,直到k为零。

  注意一下细节问题就行啦。

#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include"kth.h"
using namespace std;
int query_kth(int n_a,int n_b,int n_c,int k)
{
    int ca=0,cb=0,cc=0;
    int ta,tb,tc;
    int minn,t;
    while(k)
    {
        int t=max(0,k/3-1);
        ta=get_a(ca+t),tb=get_b(cb+t),tc=get_c(cc+t);
        minn=min(ta,min(tb,tc));t++;
        if(minn==ta) ca+=t;else if(minn==tb)    cb+=t;else cc+=t;
        k-=t;    
    }
    return minn;
}
代码
原文地址:https://www.cnblogs.com/CLGYPYJ/p/7395220.html