2021牛客暑期多校训练营3A-Guess and lies【dp】
正題
題目鏈接:https://ac.nowcoder.com/acm/contest/11254/A
題目大意
現在有一個y∈[1,n]y\in[1,n]y∈[1,n],BobBobBob每次可以選擇問AliceAliceAlice是否y≥xy\geq xy≥x,AliceAliceAlice可以說一次謊。BobBobBob要在最少次數內確定yyy的值,而AliceAliceAlice盡量使得次數最多。
現在已知第一次BobBobBob詢問的是kkk且AliceAliceAlice回答了是,對于k∈[1,n]k\in[1,n]k∈[1,n]求每個kkk BobBobBob需要的最少詢問次數。
1≤n≤20001\leq n\leq 20001≤n≤2000
解題思路
dlsdlsdls 在 WC 講的神仙題目。
對于一種情況,假設y=iy=iy=i時,AliceAliceAlice說謊的次數是固定的,記這個次數為aia_iai?,所以如果當1~n1\sim n1~n中只有一個數字滿足ai≤1a_i\leq 1ai?≤1時那么答案就是這個數字了。
然后看BobBobBob的操作,它每次可以選擇一個xxx,AliceAliceAlice可以選擇讓≥x\geq x≥x的數字或者讓<x<x<x的數字的位置ai=ai+1a_i=a_i+1ai?=ai?+1,BobBobBob需要用最少的次數使得只有一個位置ai≤1a_i\leq 1ai?≤1。
發現因為每次都是覆蓋一個前綴或者一個后綴,所以如果只保留ai=0/1a_i=0/1ai?=0/1的話那么所有的狀態肯定是若干個111+若干個000+若干個111,分別記為a/b/ca/b/ca/b/c個,我們就可以設狀態為fa,b,cf_{a,b,c}fa,b,c?進行轉移。
考慮到隨著ccc的增大我們肯定會盡量選擇中間的位置,也就是決策位置是單調遞增的,所以我們可以做到O(n3)O(n^3)O(n3)的轉移。
然后注意到這個和猜數字的規則很像,詢問次數級別不會超過log?n\log nlogn,所以我們可以考慮交換次數和一個值域,記fw,a,bf_{w,a,b}fw,a,b?表示猜測了www次能夠猜出來的aaa個000+bbb個111+ccc個000中最大的ccc,然后用決策單調性轉移。
時間復雜度:O(n2log?n)O(n^2\log n)O(n2logn)
code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=2100;int n,inf,f[20][N][N];int calc(int u,int v){int ans=19;while(ans&&f[ans-1][u][v]>=0)ans--;return ans;}int main(){scanf("%d",&n);memset(f,0xcf,sizeof(f));inf=f[0][0][0];for(int i=0;i<=1;i++)for(int j=0;j<=1-i;j++)f[0][i][j]=1-i-j;for(int i=1;i<=19;i++){for(int j=0;j<=n;j++)for(int k=0;k<=j;k++){int u=f[i-1][j-k][k];int v=f[i-1][k][j-k];if(u!=inf&&v!=inf){u=min(u,n-j);f[i][u][j]=max(f[i][u][j],v);}}for(int j=0;j<=n;j++){int v=f[i-1][j][0];if(v!=inf){for(int k=0;k<=n-j;k++){int u=f[i-1][k][j];if(u==inf)break;f[i][min(u,n-j)][j]=max(f[i][min(u,n-j)][j],v+k);f[i][min(v+k,n-j)][j]=max(f[i][min(v+k,n-j)][j],u);}}}for(int j=0;j<=n;j++)for(int k=n-j-1;k>=0;k--)f[i][k][j]=max(f[i][k][j],f[i][k+1][j]);}for(int i=0;i<n;i++)printf("%d ",calc(i,n-i));return 0;}總結
以上是生活随笔為你收集整理的2021牛客暑期多校训练营3A-Guess and lies【dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《极限竞速:地平线 5》将迎“美国汽车”
- 下一篇: AT2339-[AGC011C]Squa