想到一个部分分做法:每次考虑序列相邻两者进行询问,筛出较大者,并且首尾匹配询问,继续筛出较大者,由于两者独立,所以可以塞到一次询问里。配合当序列长度小于等于 1000 时直接暴力求最大值,可以做到 T<=8,S<=160000(grader 情况下),提交拿到了 38 分。
具体代码如下:
#include<bits/stdc++.h>
using namespace std;
random_device mt;
mt19937 rd(mt());
bitset<1000005> vis;
std::vector<int> ask(std::vector<int> a, std::vector<int> b);
int richest(int N, int T, int S) {
if(N==1000)
{
vector<int> a1,a2;
for(int i=0;i<N;i++)
for(int j=0;j<i;j++) a1.push_back(i),a2.push_back(j);
vector<int> b=ask(a1,a2);
int maxx=0;
for(int i=1;i<N;i++) if(b[i*(i-1)/2+maxx]==i) maxx=i;
return maxx;
}
vis.reset();
vector<int> a(N);
for(int i=0;i<N;i++) a[i]=i;
while(1)
{
//random_shuffle(a.begin(),a.end());随机化
int t=a.size();
if(t<=1000)
{
vector<int> a1,a2;
for(int i=0;i<t;i++)
for(int j=0;j<i;j++) a1.push_back(a[i]),a2.push_back(a[j]);
vector<int> b=ask(a1,a2);
int maxx=0;
for(int i=1;i<t;i++) if(b[i*(i-1)/2+maxx]==a[i]) maxx=i;
return a[maxx];
}
vector<int> a1,a2;
for(int i=1;i<t;i+=2) a1.push_back(a[i-1]),a2.push_back(a[i]);
for(int i=0;i<t/2;i++) a1.push_back(a[i]),a2.push_back(a[t-i-1]);
vector<int> b=ask(a1,a2);
int tt=b.size();
vector<int> c;
if(t&1) vis[a[t-1]]=1;
for(int i=0;i<tt/2;i++) vis[b[i]]=1;
if(t&1){if(vis[a[t/2]]) c.push_back(a[t/2]);}
for(int i=tt/2;i<tt;i++) if(vis[b[i]]) c.push_back(b[i]);
if(t&1) vis[a[t-1]]=0;
for(int i=0;i<tt/2;i++) vis[b[i]]=0;
a=c;
if((int)a.size()==1) return a[0];
}
return 1;
}
于是想每次访问都随机化期望减少次数,但是离奇的事发生了,我在每次循环前加上随机序列的 random_shuffle
,也就是上面代码加上注释的地方,然后就 T 了。
本地 grader 的运行效率是一模一样的,下载数据也没问题,所以想请教各位大佬这是什么情况,怀疑是死循环了,但是自己感觉没有道理触发死循环(毕竟长度小的时候跑的都还是暴力)。