交互题入门

纪念一下第一次A掉交互题。

インタラクティブ練習 (Interactive Sorting)

B - インタラクティブ練習 (Interactive Sorting)

Time Limit: 2 sec / Memory Limit: 256 MB

Score : 300 points

 

Problem Statement

This is an interactive task.

There are N balls labeled with the first N uppercase letters. The balls have pairwise distinct weights.

You are allowed to ask at most Q queries. In each query, you can compare the weights of two balls (see Input/Output section for details).

Sort the balls in the ascending order of their weights.

 

Constraints

  • (N,Q)=(26,1000), (26,100), or (5,7).

 

Partial Score

There are three testsets. Each testset is worth 100 points.

  • In testset 1, N=26 and Q=1000.
  • In testset 2, N=26 and Q=100.
  • In testset 3, N=5 and Q=7.

 

Input and Output

First, you are given N and Q from Standard Input in the following format:

N Q

 

Then, you start asking queries (at most Q times). Each query must be printed to Standard Output in the following format:

? c1 c2

 

Here each of c1 and c2 must be one of the first N uppercase letters, and c1 and c2 must be distinct.

Then, you are given the answer to the query from Standard Input in the following format:

ans

 

Here ans is either '<' or '>'. When ans is '<', the ball c2 is heavier than the ball c1, and otherwise the ball c1 is heavier than the ball c2.

Finally, you must print the answer to Standard Output in the following format:

! ans

 

Here ans must be a string of length N, and it must contain each of the first N uppercase letters once. It must represent the weights of the balls in the ascending order.

 

Judgement

  • After each output, you must flush Standard Output. Otherwise you may get 'TLE'.
  • After you print the answer, the program must be terminated immediately. Otherwise, the behavior of the judge is undefined.
  • When your output is invalid or incorrect, the behavior of the judge is undefined (it does not necessarily give 'WA').

 

Sample Code

Here is a sample solution for 100 points:

#include <cstdio>
#include <string>

using namespace std;

int main(void){
  int N,Q,i,j;

  scanf("%d%d", &N, &Q);

  string s;
  for(i=0;i<N;i++) s += (char)('A' + i);

  for(i=0;i<N;i++) for(j=0;j<N-1;j++){
    printf("? %c %c\n", s[j], s[j+1]);
    fflush(stdout);
    char ans;
    scanf(" %c", &ans);
    if(ans == '>') swap(s[j], s[j+1]);
  }

  printf("! %s\n", s.c_str());
  fflush(stdout);

  return 0;
}

 

Sample

In this sample N=3, Q=10, and the answer is 'BAC'.

InputOutput
3 10 
 ? A B
> 
 ? C B
> 
 ? A C
< 
 ! BAC

 


题意:

时间限制2s,空间限制256MB

分3个任务,每个任务100分

任务1:N=26 Q=1000

任务2:N=26 Q=100

任务3:N=5 Q=7

你有N个大写字母,他们代表一些数,这些数互不相同,你不知道这些数之间的大小关系,但你可以通过询问评测机来获得答案,询问方式为:

? c1 c2

 

c1和c2是大写字母,评测机会返回'>'或'<'

你最多能询问Q次

最后输出排好序的大写字母序列

格式为:

! ans

 

ans是排好序的序列


任务1:通过冒泡排序等O(n^2)的算法即可通过,代码在题目描述中已经给出。

任务2:通过归并排序解决,当然同时也可解决任务1

任务3:当N=5时,使用归并排序最多需要8次询问,而题目要求最多7次,于是就要用另外的算法了

这五个数分别为A,B,C,D,E

Step 1:A与B比大小,C与D比大小,耗费2次询问

Step 2:不妨设上一步得到的较小值分别为A,C,将A与C比大小,耗费1次询问

Step 3:不妨设上一步得到的较小值为A,将E用二分插入进A<C<D中,耗费2次询问

Step 4:现在出现2种情况

  • Case 1:E<A,因为A<B,所以将B用二分插入C<D中,耗费2次询问
  • Case 2:A<E,不妨设A<C<D<E,将B用二分插入C<D<E中,耗费2次询问

共计7次询问

于是问题得解

还有,交互题仅仅使用printf或cout输出是不行的,因为这样输出有时会放在缓存里,等到程序结束时一起输出,所以输出后还要加一句话来将缓存里的数据输出。

即:

fflush(stdout);

#include<bits/stdc++.h>
using namespace std;
int s[100],t[100],nex[100];
char a[10],b[10];
void gbpx(int l,int r)//归并排序
{
	if(l==r)
		return;
	int mid=(l+r)>>1;
	gbpx(l,mid);
	gbpx(mid+1,r);
	int i=l,j=mid+1,k=l;
	while(i<=mid && j<=r)
	{
		char c;
		printf("? %c %c\n",s[i]+64,s[j]+64);
		fflush(stdout);
		scanf(" %c",&c);
		if(c=='>')
			t[k++]=s[j++];
		else
			t[k++]=s[i++];
	}
	for(;i<=mid;i++,k++)
		t[k]=s[i];
	for(;j<=r;j++,k++)
		t[k]=s[j];
	for(i=l;i<=r;i++)
		s[i]=t[i];
}
inline void insert(char x,int L,int R)//二分插入
{
	int l=L,r=R;
	char c;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		printf("? %c %c\n",x,b[mid]);
		fflush(stdout);
		scanf("%c",&c);
		while(c=='\n' || c==' ')
			c=getchar();
		if(c=='>')
			l=mid+1;
		else
			r=mid-1;
	}
	for(register int i=R;i>=l;i--)
		b[i+1]=b[i];
	b[l]=x;
}
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	for(register int i=1;i<=n;i++)
		s[i]=i;
	if(n==5)
	{
		char c;
		a[1]='A';
		a[2]='B';
		a[3]='C';
		a[4]='D';
		a[5]='E';
		printf("? %c %c\n",a[1],a[2]);
		fflush(stdout);
		scanf("%c",&c);
		while(c=='\n' || c==' ')
			c=getchar();
		if(c=='>')
			swap(a[1],a[2]);
		printf("? %c %c\n",a[3],a[4]);
		fflush(stdout);
		scanf("%c",&c);
		while(c=='\n' || c==' ')
			c=getchar();
		if(c=='>')
			swap(a[3],a[4]);//Step 1
		printf("? %c %c\n",a[1],a[3]);
		fflush(stdout);
		scanf("%c",&c);
		while(c=='\n' || c==' ')
			c=getchar();
		if(c=='>')
		{
			swap(a[1],a[3]);
			swap(a[2],a[4]);
		}//Step 2
		b[1]=a[1];
		b[2]=a[3];
		b[3]=a[4];
		insert(a[5],1,3);//Step 3
		if(b[1]!=a[5])
			insert(a[2],2,4);
		else
			insert(a[2],3,4);//Step 4
		putchar('!');
		putchar(' ');
		for(register int i=1;i<=5;i++)
			putchar(b[i]);
		fflush(stdout);
		return 0; 
	} 
	gbpx(1,n);
	putchar('!');
	putchar(' ');
	for(register int i=1;i<=n;i++)
		putchar(s[i]+64);
	fflush(stdout);
	return 0;
}

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值