题面

这是一道交互题。

有一个未知的长度为

N

\tt N

N 的排列

P

\tt P

P,已知

P

1

<

P

2

\tt P_1 < P_2

P1​<P2​ 。

每次询问格式为 “

?

a

b

c

\tt?~a~b~c

? a b c ”,返回值为三元组

{

∣

P

a

−

P

b

∣

,

∣

P

b

−

P

c

∣

,

∣

P

a

−

P

c

∣

}

\tt \{|P_a-P_b|,|P_b-P_c|,|P_a-P_c|\}

{∣Pa​−Pb​∣,∣Pb​−Pc​∣,∣Pa​−Pc​∣} 的中位数。

在至多

2

n

+

420

\tt 2n+420

2n+420 次询问后,输出排列

P

\tt P

P,格式为 “

!

P

1

P

2

…

P

N

\tt!~P_1~P_2~\dots~P_N

! P1​ P2​ … PN​ ”。

然后每组数据会返回一个数,为

1

\tt1

1 则答案正确,为

−

1

\tt-1

−1 则错误,不要忘了输入这个数。

一共

t

(

1

≤

t

≤

1000

)

\tt t(1\leq t\leq1000)

t(1≤t≤1000) 组数据,保证

20

≤

N

≤

1

0

5

,

∑

N

≤

1

0

5

20\leq N\leq 10^5,\tt \sum N\leq 10^5

20≤N≤105,∑N≤105。

题解

有两种各占优势的做法。


Solution #1

首先,返回该三元组的中位数,相当于:若

P

a

>

P

b

>

P

c

\tt P_a>P_b>P_c

Pa​>Pb​>Pc​,则返回

max

⁡

{

P

a

−

P

b

,

P

b

−

P

c

}

\tt\max\{P_a-P_b,P_b-P_c\}

max{Pa​−Pb​,Pb​−Pc​}。

有了这个简化,才能更好地继续推。

该解法的核心在于:如果已经知道了

1

\tt1

1 和

2

\tt2

2 的位置(假设为

P

A

,

P

B

\tt P_A,P_B

PA​,PB​),那么可以在

n

−

2

\tt n-2

n−2 次操作后,确定整个排列。也就是分别询问

{

A

,

B

,

i

}

\tt\{A,B,i\}

{A,B,i},所得值(

q

u

e

r

y

(

A

,

B

,

i

)

\tt query(A,B,i)

query(A,B,i))

+

2

\tt+2

+2 便是

P

i

\tt P_i

Pi​ 了。

问题是怎么获得

1

\tt1

1 和

2

\tt2

2 的位置,或者说,也可以获得

N

\tt N

N 和

N

−

1

\tt N-1

N−1 的位置,总之通过

P

1

<

P

2

\tt P_1<P_2

P1​<P2​ 确定最终答案。

经过一段尝试,我们发现,如果找到这么两个位置

a

\tt a

a 和

b

\tt b

b ,满足

∣

P

a

−

P

b

∣

≤

N

−

4

3

\tt|P_a-P_b|\leq \frac{N-4}{3}

∣Pa​−Pb​∣≤3N−4​ ,处理出所有的

q

[

i

]

=

q

u

e

r

y

(

a

,

b

,

i

)

\tt q[i]=query(a,b,i)

q[i]=query(a,b,i) ,那么

q

[

i

]

\tt q[i]

q[i] 最大的

i

\tt i

i 就是

1

\tt1

1 或者

N

\tt N

N 的位置,

q

[

i

]

\tt q[i]

q[i] 严格次大的

i

\tt i

i 就是

2

\tt2

2 或者

N

−

1

\tt N-1

N−1 的位置。这样只需要多进行

N

−

2

\tt N-2

N−2 次操作。

那么,在剩下的

424

\tt424

424 次操作内,我们需要解决两个问题:

  • 找到这样的位置

    a

    ,

    b

    \tt a,b

    a,b 。

  • 找到

    1

    \tt1

    1 和

    2

    \tt2

    2 的或者

    N

    \tt N

    N 和

    N

    −

    1

    \tt N-1

    N−1 的位置

    A

    ,

    B

    \tt A,B

    A,B 。

找 a b:

我们可以证明:对于任意

13

\tt13

13 个位置,总存在

3

\tt3

3 个位置

x

,

y

,

z

\tt x,y,z

x,y,z ,满足

q

u

e

r

y

(

x

,

y

,

z

)

≤

n

−

4

6

\tt query(x,y,z)\leq\frac{n-4}{6}

query(x,y,z)≤6n−4​(

⇒

max

⁡

{

∣

P

x

−

P

y

∣

,

∣

P

y

−

P

z

∣

,

∣

P

x

−

P

z

∣

}

≤

n

−

4

3

\tt\Rightarrow \max\{|P_x-P_y|,|P_y-P_z|,|P_x-P_z|\}\leq\frac{n-4}{3}

⇒max{∣Px​−Py​∣,∣Py​−Pz​∣,∣Px​−Pz​∣}≤3n−4​)。

可以用反证法进行证明,即假设存在某

13

\tt13

13 个位置,满足

∀

{

x

,

y

,

z

}

,

max

⁡

{

∣

P

x

−

P

y

∣

,

∣

P

y

−

P

z

∣

,

∣

P

x

−

P

z

∣

}

>

n

−

4

3

\tt\forall \{x,y,z\},\max\{|P_x-P_y|,|P_y-P_z|,|P_x-P_z|\}>\frac{n-4}{3}

∀{x,y,z},max{∣Px​−Py​∣,∣Py​−Pz​∣,∣Px​−Pz​∣}>3n−4​ 。贪心地填数进去,你就会发现,刚好到

13

\tt13

13 个时,你就满足不了条件了。所以这种情况不存在,假设不成立。

找这

3

\tt3

3 个位置,需要枚举

(

13

3

)

=

286

\tt{13\choose3}=286

(313​)=286 种情况,完全足够。

找到这样的

3

\tt3

3 个位置时,任选两个就可以作

a

,

b

\tt a,b

a,b 了。

找 A B:

我们会发现,假如你确定了某个

q

[

i

]

\tt q[i]

q[i] 最大的

A

\tt A

A 作为

1

\tt1

1 的位置,那么还是有两个位置可能为

2

\tt2

2 ,一个是真

2

\tt2

2 ,一个是

N

−

1

\tt N-1

N−1 ,令其分别为

B

1

,

B

2

\tt B_1,B_2

B1​,B2​ ,我们稍稍归纳一下就会发现:

q

u

e

r

y

(

A

,

B

1

,

a

)

≤

q

u

e

r

y

(

A

,

B

2

,

a

)

q

u

e

r

y

(

A

,

B

1

,

b

)

≤

q

u

e

r

y

(

A

,

B

2

,

b

)

{\tt query(A,B_1,a)\leq query(A,B_2,a)}\\ {\tt query(A,B_1,b)\leq query(A,B_2,b)}

query(A,B1​,a)≤query(A,B2​,a)query(A,B1​,b)≤query(A,B2​,b)

而且最多只有一个取等。因此便可以把

B

1

\tt B_1

B1​ 判断出来了。

CODE

#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) ((-x) & (x))
#define INF 0x3f3f3f3f
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
inline int ask(int a,int b,int c) {
cout<<"? "<<a<<" "<<b<<" "<<c<<endl;
int as; cin>>as; return as;
}
int a[MAXN],p[MAXN],ar[MAXN];
vector<int> bu[MAXN];
int main() {
srand(time(0));
int T;cin>>T;
while(T --) {
cin>>n;
for(int i = 1;i <= n;i ++) bu[i].clear(),a[i] = 0,ar[i] = i;
random_shuffle(ar + 1,ar + 1 + n);
int A = 1,B = 2,C = 3,as,flag1 = 0;
for(A = 1;A <= 11;A ++) {
for(B = A+1;B <= 12;B ++) {
for(C = B+1;C <= 13;C ++) {
if((as=ask(A,B,C)) <= ((n-4)/6)) {
flag1 = 1; break;
}
}
if(flag1) break;
}
if(flag1) break;
}
int mi = n+1,ct = 1,ct2 = 0,ma = 0;
for(int i = 1;i <= n;i ++) {
if(i != A && i != B) {
a[i] = ask(A,B,i);
if(a[i] < mi) mi = a[i],ct = 1;
else if(a[i] == mi) ct ++;
if(a[i] == 2) ct2 ++;
ma = max(ma,a[i]);
bu[a[i]].push_back(i);
}
}
int H = bu[ma][0],H2 = bu[ma-1][0];
if((int)bu[ma-1].size() > 1) {
int H3 = bu[ma-1][1];
if(ask(H,H2,A) <= ask(H,H3,A) && ask(H,H2,B) <= ask(H,H3,B)) {
H2 = H2;
}
else H2 = H3;
}
p[H] = 1; p[H2] = 2;
for(int i = 1;i <= n;i ++) {
if(i != H && i != H2) {
p[i] = 2 + ask(H,H2,i);
}
}
if(p[1] > p[2]) {
for(int i = 1;i <= n;i ++) p[i] = n-p[i]+1;
}
cout<<"!";
for(int i = 1;i <= n;i ++) cout<<" "<<p[i];
cout<<endl;
int AC; cin>>AC;
}
return 0;
}

Solution #2

非常精妙的做法,不愧是

O

n

e

I

n

D

a

r

k

\tt OneInDark

OneInDark !

主要是选择两对数来进行序列

q

\tt q

q 的确定,通过

q

\tt q

q 和

q

′

\tt q'

q′ 确定原序列。这里笔者就不展开了。原博客还是写了满大页的。

[CF1526F] Median Queries(交互 / 构造)的更多相关文章

  1. B - Median Pyramid Easy 构造题

    B - Median Pyramid Easy Time limit : 2sec / Memory limit : 256MB Score : 400 points Problem Statemen ...

  2. $AT2163\ Median\ Pyramid\ Easy$ 构造

    正解:构造 解题报告: 传送门$QwQ$ 考虑如果有两个相邻格子是相同数字那么它们以上这两列就都会是这列数字(显然$QwQ$? 所以考虑只要构造出第$n-1$行的中心和中心右侧($or$左侧一样的$Q ...

  3. Gym - 100851J: Jump(交互+构造+(大胆瞎搞)))

    题意:给定长度为N的01串,现在让你猜这个串,猜的次数要不超过N+500次. 每次你猜一个串,系统会返回N/2,或N,或0.当且当有N/2个位置猜对,N个位置猜对,其他. 思路:因为信息不多,没有关联 ...

  4. Codeforces Round #669 (Div. 2) C. Chocolate Bunny (交互,构造)

    题意:有一个长度为\(n\)的隐藏序列,你最多可以询问\(2n\)次,每次可以询问\(i\)和\(j\)位置上\(p[i]\ mod\ p[j]\)的结果,询问的格式是\(?\ x\ y\),如果已经 ...

  5. Codeforces Round #356 (Div. 2)

    A. Bear and Five Cards time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  6. Kafka connect快速构建数据ETL通道

    摘要: 作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 业余时间调研了一下Kafka connect的配置和使用,记录一些自己的理解和心得,欢迎 ...

  7. Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers

    链接:https://codeforces.com/contest/1167/problem/B 题意: This is an interactive problem. Remember to flu ...

  8. OrmLite使用小结(一)

    在使用OrmLite过程中,遇到了不少问题.鉴于中文文档比較少,看英文文档又不知道怎样看起.仅仅能遇到问题查找解决方法并整理出来,如有错误,希望能指正! ** 1.模糊条件查询 ** 使用条件查询时. ...

  9. 【Python】使用cmd模块构造一个带有后台线程的交互命令行界面

    最近写一些测试工具,实在懒得搞GUI,然后意识到python有一个自带模块叫cmd,用了用发现简直是救星. 1. 基本用法 cmd模块很容易学到,基本的用法比较简单,继承模块下的Cmd类,添加需要的功 ...

随机推荐

  1. 『忘了再学』Shell基础 — 30、sed命令的使用

    目录 1.sed命令说明 2.行数据操作 (1)查看文件中的数据 (2)删除文件中的数据 (3)向文件中追加数据 (4)向文件中插入数据 (5)修改文件中的多行数据(删除,追加,插入) (6)替换文件 ...

  2. Redis初启(一)

    1.数据库存存储性能优化 在mysql的文章专题中我写过了关于传统关系型数据库的一些优化思路,整体来说,通过优化之后能够提升程序访问数据库的计算性能.但是还是有一些情况,即便是优化之后,使用传统关系型 ...

  3. Vue之封装二次axios

    第一步,首先安装axios,这里推荐局部安装 npm i -D axios 第二步,在src目录下创建request文件夹,然后在里面创建两个文件http.js.api.js http.js impo ...

  4. 针对elementUI 中InfiniteScroll按需引入的一点注意事项

    大家为了节省空间,常常进行按需引入来节省空间,这里我给大家来介绍一下element中按需引入无限滚动指令注意的事项. 针对前面element 按需引入的一些配置这里就不再详细介绍了. 那么这里讲的是在 ...

  5. spring中的bean生命周期

    1.实例化(在堆空间中申请空间,对象的属性值一般是默认值.通过调用createBeanInstance()方法进行反射.先获取反射对对象class,然后获取默认无参构造器,创建对象) 2.初始化(就是 ...

  6. 【python基础】第09回 数据类型内置方法 01

    本章内容概要 1.数据类型的内置方法简介 2.整型相关方法 3.浮点型相关方法 4.字符串相关方法 5.列表相关方法 本章内容详情 1.数据类型的内置方法简介 数据类型是用来记录事物状态的,而事物的状 ...

  7. 相约 DTCC 2021 | Tapdata 受邀分享:如何打造面向 TP 业务的数据平台架构

      2021第十二届中国数据库技术大会(DTCC)将于2021年10月18-20日,在北京国际会议中心举行,Tapdata 创始人唐建法受邀分享:如何打造面向 TP 业务的数据平台架构.   演讲时间 ...

  8. .NET Core 实现后台任务(定时任务)IHostedService(一)

    原文链接:https://www.cnblogs.com/ysmc/p/16456787.html 最近有小伙伴问道,在 .Net Core 中,如何定时执行任务,而因为需要执行的任务比较简单,并不想 ...

  9. 函数式编程思想概述和冗余的Runnable代码

    函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方法 相对而言,面向对象过分强调必须通过对象的形式来做事情,而函数式的思想是尽量忽略复杂的面向对象的复杂语法--是强调做什么而不是以什么 ...

  10. npm相关资料

    npm 源的配置 命令行模式 npm install XXX --registry https://registry.npmmirror.com/ 项目模式 在项目更目录新建.npmrc 文件,内容 ...