#交互,dp#洛谷 7998 [WFOI - 01] 猜数(guess)

题目传送门


分析

首先要搞清楚,交互库的自适应会让区间长度尽可能增大(答案自适应)

也就是说,如果现在区间为 [l,r],你选取的区间为 [l,r]

那么交互库会让你的区间变成 [l,r1][l+1,r] 中区间更长的那一个,不妨枚举这个长度

dp[i] 表示区间长度为 i 时的最小询问总代价,也就是要决定下一步让交互库缩短到的区间长度,设其为 j

那么就要保证 1ij+1jn,且此时询问代价为 1j(ij+1)+1=12ji

那么 dp[i]=mini+12ji{dp[j1]+12ji}

按照最优决策点决策就能将总代价卡在能过的范围内,且 j 的选取可以将范围缩小到 p[i1]±Δ

由于并不需要非常精确地求出最小的 dp 值,所以这样预处理的复杂度就是 O(nΔ)


代码

#include <iostream>
using namespace std;
const int N=100011;
double dp[N]; int n,pos[N];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n,pos[1]=1;
    for (int i=2;i<=n;++i){
        dp[i]=i;
        int L=max((i+2)>>1,pos[i-1]-800);
        int R=min(i,pos[i-1]+800);
        for (int j=L;j<=R;++j){
            double t=dp[j-1]+1.0/(j-(i-j+1)+1);
            if (dp[i]>t) dp[i]=t,pos[i]=j;
        }
    }
    int l=1,r=n;
    while (l<r){
        int lmid=r-pos[r-l+1]+1,rmid=l+pos[r-l+1]-1,x,opt;
        cout<<"? "<<lmid<<' '<<rmid<<'\n',cout.flush();
        cin>>x>>opt;
        switch (opt){
            case 0:{
                l=x+1;
                break;
            }
            case 1:{
                cout<<"! "<<x<<'\n';
                cout.flush();
                l=r=x;
                break;
            }
            case 2:{
                r=x-1;
                break;
            }
        }
    }
    cout<<"! "<<l<<'\n';
    cout.flush();
    return 0;
}
posted @   lemondinosaur  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-05-04 #KD-Tree#洛谷 4849 寻找宝藏
点击右上角即可分享
微信分享提示