Codeforces Round #719 (Div. 3) F2 题解(神仙证明+线段树上二分)
题目链接
题目思路
本质上就是利用线段树上二分的思维但是没有用线段树而已
最关键的是如何证明这样的查询次数少于\(6e4\)次
由于节点是\(1e5\)个
那么这颗线段树的深度最多\(18\)
最坏的情况是深度\(14\)全部占满那么查询的次数就是\(2^{14}-1\)
而最多\(1e4\)次查询下面四层节点最多查询\(4\)个
那么最多查询\(4e4+2^{14}-1\)
代码
#include<bits/stdc++.h>
#define debug printf("\n I am here\n");
#define fi first
#define se second
#define pii pair<int,int>
typedef long long ll;
const int maxn=2e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
using namespace std;
int n,t;
int k;
map<pair<int,int>,int> mp;
int cal(int l,int r){
if(mp.count({l,r})) return mp[{l,r}];
printf("? %d %d\n",l,r);
fflush(stdout);
int re;
scanf("%d",&re);
mp[{l,r}]=r-l+1-re;
return mp[{l,r}];
}
void query(int l,int r,int k){
mp[{l,r}]--;
if(l==r){
printf("! %d\n",l);
fflush(stdout);
return ;
}
int mid=(l+r)/2;
if(cal(l,mid)>=k) query(l,mid,k);
else query(mid+1,r,k-cal(l,mid));
}
int main(){
scanf("%d%d",&n,&t);
while(t--){
scanf("%d",&k);
query(1,n,k);
}
return 0;
}
不摆烂了,写题

浙公网安备 33010602011771号