Codeforces 1286C/1287E Madhouse (交互题)

题目链接

C1: http://codeforces.com/contest/1286/problem/C1
C2: http://codeforces.com/contest/1286/problem/C2

题解

首先考虑C1怎么做: 先询问整个串,再询问前\((n-1)\)个字符。二者相比对,对于每一个\(l=1..n\), 前者都比后者多一个长度为\(l\)的字符串,也就是长度为\(l\)的后缀。求出这些后缀是什么,然后后缀之间互相比对,就可以知道每个位置的字符了。
考虑问一遍整个串。位置\(i\)上的字符在整个串的长度为\(l\)的子串(\(l\gt \frac{n}{2}\))共出现了\(\min(i,n-i+1,n-l+1)\)次。将\(l\)\((l+1)\)作差,那么剩下的就是\([n-l+1,l]\)这段区间内的字符各出现了一次。再将作差后的\(l\)\((l-1)\)作差,剩下的是\(l\)\((n-l+1)\)这两个字符。
但是剩下两个字符非常难以判断。考虑用刚才的方法求出前一半,去掉前一半的影响,就可以通过差出来的字符确定答案了。
总询问次数约\(0.75n^2\).
注意特判\(n=1\).

代码

#include
#define llong long long
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 101;
const int S = 26;

char str[N+3];

namespace Subtask
{
    int a[N+3][N+3][S+3],cnta[N+3],b[N+3][N+3][S+3],cntb[N+3];
    bool fa[N+3][N+3],fb[N+3][N+3];
    int cur[S+3];
    char ans[N+3];
    void solve(int n,char ans[])
    {
        cout<<'?'<<' '<<1<<' '<>str+1; int len = strlen(str+1);
            cnta[len]++; for(int j=1; j<=len; j++) a[len][cnta[len]][str[j]-96]++;
        }
        cout<<'?'<<' '<<1<<' '<>str+1; int len = strlen(str+1);
            cntb[len]++; for(int j=1; j<=len; j++) b[len][cntb[len]][str[j]-96]++;
        }
        for(int i=1; i<=n; i++)
        {
            int id = 0;
            for(int k=1; k<=cntb[i]; k++)
            {
                bool found = false;
                for(int j=1; j<=cnta[i]; j++)
                {
                    if(fa[i][j]) continue;
                    bool same = true;
                    for(int s=1; s<=S; s++) {if(a[i][j][s]!=b[i][k][s]) {same = false; break;}}
                    if(same) {found = true; fa[i][j] = true; break;}
                }
                if(!found) {id = k; break;}
            }
            for(int s=1; s<=S; s++)
            {
                if(b[i][id][s]!=cur[s]) {cur[s]++; ans[n-i+1] = s+96; break;}
            }
        }
    }
}

int a[N+3][N+3][S+3],cnta[N+3];
int tot[N+3][S+3];
int dif[N+3][S+3];
char ans[N+3];
int n;

int main()
{
    cin>>n;
    if(n==1)
    {
        cout<<'?'<<' '<<1<<' '<<1<>ans;
        cout<<'!'<<' '<>1;
    Subtask::solve(nn,ans);
    cout<<'?'<<' '<<1<<' '<>str+1; int len = strlen(str+1);
        cnta[len]++; for(int j=1; j<=len; j++) a[len][cnta[len]][j] = str[j]-96,tot[len][str[j]-96]++;
    }
    for(int l=nn+1; l<=n; l++)
    {
        for(int i=1; i<=nn; i++)
        {
            tot[l][ans[i]-96] -= min(i,n-l+1);
        }
//      printf("tot[%d]: ",l); for(int j=1; j<=S; j++) printf("%d ",tot[l][j]); puts("");
    }
    for(int l=nn+1; l<=n; l++)
    {
        for(int i=1; i<=S; i++)
        {
            dif[l][i] = tot[l][i]-tot[l+1][i];
            if(dif[l][i]!=dif[l-1][i]) {ans[l] = i+96;}
        }
    }
    cout<<'!'<<' '<

你可能感兴趣的:(Codeforces 1286C/1287E Madhouse (交互题))