题解:P17854 [LBA-OI R6 B] 凌云沐雨
Monarch_Richest · · 题解
题意
有一个未知的长度为
每次询问可以给出一个下标的有序集合
我们需要在不超过
思路
设:我们已经知道了一些下标
现在需要确定新下标为
置换环数量:
-
- 从
r 开始跳到原下标r 的r+1 ,然后r+1 又跳到原下标r+1 的r+2 ,……,依次类推,直到k+1 跳到r 形成一个大环;
所以,交互库返回的数
算法
维护一个有序下标序列
然后依次加入下标
- 询问集合
ans 加x ; - 插入
x 到ans 下标为c 的位置;
因此,处理完后
所以
:::info[正确性证明]
- 假设:处理完前
k 个下标,则ans 里一定满足:A_{ans_0}<A_{ans_1}<\dots<A_{ans_k} ; - 步骤:加入新下标
x 时,序列为ans_0,ans_1,\dots,ans_k ,前k 个值严格递增。设A_x 在其中的排名为r ,则由核心观察,返回的环数c=r 。把x 插入到ans 的第r 个位置后,新的序列仍然按A 值升序排列。归纳成立。 处理完全部n 个下标后,ord 是按值升序排列的下标序列,因此,排列被唯一确定。 ::: 询问次数n-1 ,足以通过此题。 :::success[AC code]#include<bits/stdc++.h> typedef long long ll; using namespace std; const int MAXN=1005; int n,k,c; int a[MAXN]; vector<int>p; int main() { ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n>>k; p.emplace_back(1); for(int i=2;i<=n;i++) { cout<<"\n? "<<i; for(int&x:p) cout<<' '<<x; cout<<' '<<i<<endl; cin>>c; p.insert(p.begin()+(c-1),i); } for(int i=0;i<n;i++) a[p[i]]=i+1; cout<<"\n!"; for(int i=1;i<=n;i++) cout<<' '<<a[i]; cout<<'\n'; return 0; }
:::