Codeforces Round #616 (Div. 2) F. Coffee Varieties 交互题

F. Coffee Varieties

time limit per test1 second
memory limit per test256 megabytes

This is the easy version of the problem. You can find the hard version in the Div. 1 contest. Both versions only differ in the number of times you can ask your friend to taste coffee.

This is an interactive problem.

You're considering moving to another city, where one of your friends already lives. There are n cafés in this city, where n is a power of two. The i-th café produces a single variety of coffee ai.

As you're a coffee-lover, before deciding to move or not, you want to know the number d of distinct varieties of coffees produced in this city.

You don't know the values a1,…,an. Fortunately, your friend has a memory of size k, where k is a power of two.

Once per day, you can ask him to taste a cup of coffee produced by the café c, and he will tell you if he tasted a similar coffee during the last k days.

You can also ask him to take a medication that will reset his memory. He will forget all previous cups of coffee tasted. You can reset his memory at most 30 000 times.

More formally, the memory of your friend is a queue S. Doing a query on café c will:

Tell you if ac is in S;
Add ac at the back of S;
If |S|>k, pop the front element of S.
Doing a reset request will pop all elements out of S.

Your friend can taste at most 2n2k cups of coffee in total. Find the diversity d (number of distinct values in the array a).

Note that asking your friend to reset his memory does not count towards the number of times you ask your friend to taste a cup of coffee.

In some test cases the behavior of the interactor is adaptive. It means that the array a may be not fixed before the start of the interaction and may depend on your queries. It is guaranteed that at any moment of the interaction, there is at least one array a consistent with all the answers given so far.

Input

The first line contains two integers n and k (1≤k≤n≤1024, k and n are powers of two).

It is guaranteed that 2n2k≤20 000.

Interaction
You begin the interaction by reading n and k.

To ask your friend to taste a cup of coffee produced by the café c, in a separate line output
? c

Where c must satisfy 1≤c≤n. Don't forget to flush, to get the answer.

In response, you will receive a single letter Y (yes) or N (no), telling you if variety ac is one of the last k varieties of coffee in his memory.

To reset the memory of your friend, in a separate line output the single letter R in upper case. You can do this operation at most 30 000 times.
When you determine the number d of different coffee varieties, output
! d

In case your query is invalid, you asked more than 2n2k queries of type ? or you asked more than 30 000 queries of type R, the program will print the letter E and will finish interaction. You will receive a Wrong Answer verdict. Make sure to exit immediately to avoid getting other verdicts.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

fflush(stdout) or cout.flush() in C++;
System.out.flush() in Java;
flush(output) in Pascal;
stdout.flush() in Python;
see documentation for other languages.

Hack format

The first line should contain the word fixed

The second line should contain two integers n and k, separated by space (1≤k≤n≤1024, k and n are powers of two).

It must hold that 2n2k≤20 000.

The third line should contain n integers a1,a2,…,an, separated by spaces (1≤ai≤n).

Examples

input
4 2
N
N
Y
N
N
N
N
output
? 1
? 2
? 3
? 4
R
? 4
? 1
? 2
! 3
input
8 8
N
N
N
N
Y
Y
output
? 2
? 6
? 4
? 5
? 2
? 5
! 6

Note

In the first example, the array is a=[1,4,1,3]. The city produces 3 different varieties of coffee (1, 3 and 4).

The successive varieties of coffee tasted by your friend are 1,4,1,3,3,1,4 (bold answers correspond to Y answers). Note that between the two ? 4 asks, there is a reset memory request R, so the answer to the second ? 4 ask is N. Had there been no reset memory request, the answer to the second ? 4 ask is Y.

In the second example, the array is a=[1,2,3,4,5,6,6,6]. The city produces 6 different varieties of coffee.

The successive varieties of coffee tasted by your friend are 2,6,4,5,2,5.

题意

你来到一个城市,这个城市有n个咖啡馆,每个咖啡馆都销售一种咖啡,你现在想知道这个城市一共有多少种咖啡在卖。

你可以让你的朋友去第i个咖啡馆喝咖啡,你的朋友会告诉你这咖啡时候和他喝过的前k个咖啡的味道存在相同。

easy版本你可以问2n2/k次,hard版本只能问3n2/2k次。

题解

视频题解:https://www.bilibili.com/video/av86529667/

考虑最暴力的做法,你依次让朋友去咖啡馆1,咖啡馆2,这时候你就知道咖啡馆2和1是否相同了,然后这时候你清理一下记忆;然后你让朋友去13,去14,然后去23,24,34。这样你就能知道前4家咖啡馆两两之间的关系了,但是这肯定询问次数很多。

div2的easy版本,你按照大小k/2来进行分块,一共可以分成n/(k/2)块,然后你依次询问第一块,第二块;第一块,第三块;第一块,第四块;第二块,第三块;第二块,第四块;第三块,第四块。由于你每次都询问两块,每块的大小是k/2,加在一起恰好是k,所以你每一对你都能知道全部的信息,这样询问的话,你一共询问次数是(2n^2-kn)/(k),恰好是满足easy版本的。

div1的hard版本,我们考虑问完第一块,第二块之后,我们紧接着问第三块,我们会发现第三块的记忆覆盖了第一块,实际上我们相当于问了12和23。 所以我只要连续的去问就可以了,这样的询问次数恰好是放缩到3n^2/2k。

代码

 #include<bits/stdc++.h>
using namespace std;
const int maxn = 30006;
int n,k;
int good[maxn];
void reset(){
    cout<<"R"<<endl;
}
bool query(int x){
    cout<<"? "<<x+1<<endl;
    string s;cin>>s;
    if(s[0]=='Y')return true;
    return false;
}
int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++)
        good[i]=1;
    if(k==1){
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                reset();
                query(i);
                if(query(j)){
                    good[j]=false;
                }
            }
        }
    }else{
        int block=k/2;
        int m=n/block;
        for(int jump=1;jump<m;jump++){
            for(int start=0;start<jump&&start+jump<m;start++){
                reset();
                for(int i=start;i<m;i+=jump){
                    for(int x=i*block;x<(i+1)*block;x++){
                        if(query(x)){
                            good[x]=false;
                        }
                    }
                }
            }
        }
    }
    int ans = 0;
    for(int i=0;i<n;i++){
        if(good[i])ans++;
    }
    cout<<"! "<<ans<<endl;
}
posted @ 2020-02-03 19:47  qscqesze  阅读(573)  评论(0编辑  收藏  举报