Codeforces 1286C/1287E Madhouse (交互题)
生活随笔
收集整理的這篇文章主要介紹了
Codeforces 1286C/1287E Madhouse (交互题)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接
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}\))共出現(xiàn)了\(\min(i,n-i+1,n-l+1)\)次。將\(l\)和\((l+1)\)作差,那么剩下的就是\([n-l+1,l]\)這段區(qū)間內的字符各出現(xiàn)了一次。再將作差后的\(l\)和\((l-1)\)作差,剩下的是\(l\)和\((n-l+1)\)這兩個字符。
但是剩下兩個字符非常難以判斷??紤]用剛才的方法求出前一半,去掉前一半的影響,就可以通過差出來的字符確定答案了。
總詢問次數(shù)約\(0.75n^2\).
注意特判\(n=1\).
代碼
#include<bits/stdc++.h> #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<<' '<<n-1<<' '<<endl; cout.flush();for(int i=1; i<=(n-1)*n/2; i++){cin>>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<<' '<<n<<' '<<endl; cout.flush();for(int i=1; i<=n*(n+1)/2; i++){cin>>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<<endl; cout.flush();cin>>ans;cout<<'!'<<' '<<ans<<endl; cout.flush();return 0;}else if(n==2){Subtask::solve(2,ans);cout<<'!'<<' '<<ans+1<<endl; cout.flush();return 0;}int nn = (n+1)>>1;Subtask::solve(nn,ans);cout<<'?'<<' '<<1<<' '<<n<<endl; cout.flush();for(int i=1; i<=n*(n+1)/2; i++){cin>>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<<'!'<<' '<<ans+1<<endl; cout.flush();return 0; }總結
以上是生活随笔為你收集整理的Codeforces 1286C/1287E Madhouse (交互题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PKUWC2020游记与题面整理
- 下一篇: HDU 6741 MUV LUV UNL