Codeforces Round #646 (Div. 2) 参与排名人数14203
[codeforces 1363D] Guess The Maximums 交互式程序+二分查找
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址http://codeforces.com/contest/1363/problem/D
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
D - Guess The Maximums | GNU C++17 | Accepted | 62 ms | 0 KB |
交互式程序,Input数据表示服务器提供给程序的数据,Output数据,表示程序询问服务器的数据。
题意极难理解,太绕了。
交互式程序,一个难点,测试太难了。
样例解释如下
Input:
1
4 2
2 1 3
2 2 4
1
2
3
4
Correct
Output:
? 1 1
? 1 2
? 1 3
? 1 4
! 4 3
样例解释如下:
编程者的程序发起output:? 1 1
询问A[1]最大值
服务器(也即测评机)回复input:1
A[1]最大值是1
编程者的程序发起output:? 1 2
询问A[2]最大值
服务器(也即测评机)回复input:2
A[2]最大值是2
编程者的程序发起output:? 1 3
询问A[3]最大值
服务器(也即测评机)回复input:3
A[3]最大值是3
编程者的程序发起output:? 1 4
询问A[4]最大值
服务器(也即测评机)回复input:4
A[4]最大值是4
故数组A={1,2,3,4}
input:
4 2
表示数组A中有4个元素,2表示有2个密码
2 1 3
表示扣除数组A中的A[1],A[3]元素,剩下的元素是A[2],A[4],在剩下元素中取最大值,是4
2 2 4
表示扣除数组A中的A[2],A[4]元素,剩下的元素是A[1],A[3],在剩下元素中取最大值,是3
故对应的密码是4 3
编程者的程序发起output:
! 4 3
服务器(也即测评机)回复input:
Correct
针对后面的AC代码,重新设计样例的输入输出数据
Input:
1
4 2
2 1 3
2 2 4
4
2
3
3
Correct
Output:
? 4 1 2 3 4
? 2 1 2
? 1 3
? 2 1 3
! 4 3
本题中还有个关键点是分组间没有交集,那么对于最大数对应的下标,最多在一个分组里面出现,所以剩下k-1个分组的值固定为这个最大值,我们用一次询问求出最大值。
然后我们二分找这个最大值在哪个区间,n≤1000,所以最多二分10次。
最大值下标所在分组的值再单独求一次,刚好12次询问。
注意,提交密码这次,不计入12次询问.Guessing the password does not count towards the number of queries asked.
AC代码如下
#include <stdio.h>
#define maxn 1010
int color[maxn],q[maxn],qn;
char s[20];
void solve(){
int n,k,c,i,j,p,l,r,maxx,mid,ret;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)color[i]=0;
for(i=1;i<=k;i++){
scanf("%d",&c);
for(j=1;j<=c;j++)scanf("%d",&p),color[p]=i;//color[]染色,区分数据分属的slots
}
printf("? %d",n);//第1次,询问最大值
for(i=1;i<=n;i++)printf(" %d",i);
printf("\n");
fflush(stdout);
scanf("%d",&maxx);
l=0,r=n;//二分查找maxx所在位置,最多查找10次,2^10=1024,n最大是1000个
while(l+1<r){
mid=(l+r)/2;
printf("? %d",mid-l);
for(i=l+1;i<=mid;i++)printf(" %d",i);
printf("\n");
fflush(stdout);
scanf("%d",&ret);
if(ret==maxx)r=mid;
else l=mid;//ret<maxx
}
qn=0;//查找扣除最大值后的数据对应的最大值
for(i=1;i<=n;i++)
if(color[i]!=color[r])q[++qn]=i;
printf("? %d",qn);
for(i=1;i<=qn;i++)printf(" %d",q[i]);
printf("\n");
fflush(stdout);
scanf("%d",&ret);
printf("!");//发送密码
for(i=1;i<=k;i++)
if(color[r]==i)printf(" %d",ret);
else printf(" %d",maxx);
printf("\n");
fflush(stdout);
scanf("%s",s);//接收Correct
}
int main(){
int t;
scanf("%d",&t);
while(t--)solve();
return 0;
}
类似题目