uva 13598

/*
   题目的大意是  给你 N 学生 然后 给前 K个学生编号了 给定的 号码 ,
   然后你按照 使得接下来学生 学号尽量小的 方法 从第 K+1个学生开始编号 
   每个号码 自然只能用一次,
    解答 :   先将编好的号码排好序,排完后 记录他们之间的 空格数,进行二分查找
    有三种情况
      1、学生就在 1至K中  
      2、学生在 K+1 到 D(K个学生中编号最大的那个数)
      3、学生在D以后
      1、3 都很好求,
      对于第二种计算 他距离 第K个 学生都少位 ,然后再 之前算好的空格中 安排他 
      我为何如此的弱 想了 一天才明白是这样做的 之前的 想法还 wa了 很多次
      我为何如此的弱
*/

#include <iostream>
#include <cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=50005;
int N[maxn],V[maxn],G[maxn];
int n,K,Q;
int bird(int D){
    int L=0,R=K,mid;
    while(L<R){
        mid=L+(R-L)/2;
        if(G[mid]>=D) R=mid;
        else L=mid+1;
    }
    if(G[L]>=D)L--;
    int Val=D-G[L]+V[L];
    return Val;
}
int main()
{
   V[0]=0;
   int t;
   scanf("%d",&t);
   for(int KA=1;KA<=t;KA++){
     printf("Case %d:\n",KA);
        scanf("%d%d%d",&n,&K,&Q);
    for(int i=1;i<=K;i++){
        scanf("%d",&N[i]);
        V[i]=N[i];
    }
    sort(V+1,V+(K+1));
    G[K]=0;
    for(int i=1;i<=K;i++)
        G[i]=V[i]-V[i-1]-1+G[i-1];
    while(Q--){
            int D;
        scanf("%d",&D);
        if(D<=K){ printf("%d\n",N[D]);continue;}
        if(D>V[K]){ printf("%d\n",D);continue;}
        D=bird(D-K);
        printf("%d\n",D);
    }

   }

    return 0;
}


posted @ 2014-03-04 22:45  来自大山深处的菜鸟  阅读(167)  评论(0)    收藏  举报