cfEduRound-130-Div-2-Summary


Educational Codeforces Round 130 (Div. 2)

CONTEST传送门

战况

Standing

Standing

Rating

Rating

补题

D - Guess The String

题目大意

这是一道交互题,首先输入一个整数,表示一个字符串的长度(1<=n<=1000)。我们需要通过询问推这个字符串并最终输出,询问包括两种

  • ? 1 i

    表示询问第i个位置的字符是什么,将输入一个字符表示答案。

  • ? 2 l r

    表示询问从下标l到r,中间有多少个不同的字母,将输入一个整数表示答案。

第一种询问不能超过26次,第二种询问不能超过6000次。

当时的思路

先用一个整数表示一个位置的字符,相同的整数表示同一个字符。

遍历字符串,对于每一个位置 i,从当前位置 i 往前遍历 j ,每找到一个此次遍历未见过的字符,便询问 ? 2 i j ,找到那个第一个等于 区间已知字符的不同的数量+1 的位置,那个位置之前遍历的那个位置的字符便对应于位置 i 的字符。

最后再询问每一个整数对应的字符。

错因

第二种询问的询问次数过多。

改进

因为是26个字母,注意到 $\log_2(26)=4.7\leq 5$ ,于是我们便可以使用二分进行查询,即可通过。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<set>
#include<map>
#include<cmath>
#include<iostream>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define Inf 0x3f3f3f3f
//#define int long long
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
typedef pair<int,P> PP;
const int MAXX=1005;
const double eps=0.0000001;

struct CC{
char ans;
int num;
}a[MAXX];
int n,num_cnt,last[MAXX],s[MAXX];
char getans[MAXX];

inline void solve_it(){
scanf("%d",&n);
a[1].num=num_cnt=1;
last[1]=1;
for(int i=2;i<=n;++i){
int l=1,r=num_cnt+1,mid,in;
for(int j=1;j<=num_cnt;++j)
s[j]=last[j];
sort(s+1,s+num_cnt+1);

while(l<r){
mid=(l+r)/2;
printf("? 2 %d %d\n",s[mid],i);
fflush(stdout);
scanf("%d",&in);
if(in==num_cnt-mid+1)//=n
l=mid+1;
else
r=mid;
}

if(l==1){
a[i].num=++num_cnt;
last[num_cnt]=i;
}
else{
int flag=s[l-1];
for(int j=1;j<=num_cnt;++j)
if(last[j]==flag){
a[i].num=j;
last[j]=i;
break;
}
}
}

for(int i=1;i<=n;++i){
if(!getans[a[i].num]){
printf("? 1 %d\n",i);
fflush(stdout);
char in;
cin>>in;
getans[a[i].num]=in;
}
a[i].ans=getans[a[i].num];
}

printf("! ");
for(int i=1;i<=n;++i)
printf("%c",a[i].ans);
printf("\n");
fflush(stdout);
}

signed main(){
// int T;scanf("%d",&T);
// while(T--)
solve_it();

return 0;
}

总结

当时脑子里也出现过使用二分的想法,但是由于二分写的太少,非常不熟练,短时间内无法写出来,于是便放弃了二分的想法。

还是得多练二分。


文章作者: Shaun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Shaun !
评论
  目录