当前位置:   article > 正文

Codeforces Round 890 (Div. 2) D. More Wrong(交互题 贪心/启发式 补写法)

Codeforces Round 890 (Div. 2) D. More Wrong(交互题 贪心/启发式 补写法)

题目

t(t<=100)组样例,长为n(n<=2000)的序列

交互题,每次你可以询问一个区间[l,r]的逆序对数,代价是(r-l)^2

要在5n^2的代价内问出最大元素的位置,输出其位置

思路来源

neal

Codeforces Round 890 (Div. 2) supported by Constructor Institute D (交互+分治) 附加强 - 知乎

题解

赛中开题顺序大失败没看这个sb题

赛后用一种不超过4n^2的搞过去了,也就是分治左右区间,

找到左区间和右区间的极大值的位置,

然后询问两次,决定是左更大还是右更大

看见neal这个最优次数不超过3n^2,补一下

感觉有点哈夫曼树贪心的意思,也有点启发式NTT的合并方式

实际就是当还有x个位置都可以成为答案时,

把他们按位置增序维护在链表里,

每次遍历链表,找到位置最接近的两个数询问

复杂度O(n^2)

构造

根据这个尝试去构造对应的hack方法,

于是,想到的最接近3n方次数的构造方法是

先把n和n-1放两边,n-2放中间,然后递归左右

n=9时,数组形如

9 4 6 3 7 2 5 1 8

证明

 

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define rep(i,a,b) for(int i=(a);i<=(b);++i)
  4. #define per(i,a,b) for(int i=(a);i>=(b);--i)
  5. typedef long long ll;
  6. typedef double db;
  7. typedef pair<ll,ll> PI;
  8. #define fi first
  9. #define se second
  10. #define pb push_back
  11. #define dbg(x) cerr<<(#x)<<":"<<x<<" ";
  12. #define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
  13. #define SZ(a) (int)(a.size())
  14. #define sci(a) scanf("%d",&(a))
  15. #define pt(a) printf("%d",a);
  16. #define pte(a) printf("%d\n",a)
  17. #define ptlle(a) printf("%lld\n",a)
  18. #define debug(...) fprintf(stderr, __VA_ARGS__)
  19. #define ll long long
  20. #define ull unsigned ll
  21. const int N=2e3+10;
  22. int t,n,dp[N][N];
  23. int cal(int l,int r){
  24. if(l==r)return 0;
  25. if(~dp[l][r])return dp[l][r];
  26. printf("? %d %d\n",l,r);
  27. fflush(stdout);
  28. int v;
  29. scanf("%d",&v);
  30. return dp[l][r]=v;
  31. }
  32. void out(int x){
  33. printf("! %d\n",x);
  34. fflush(stdout);
  35. }
  36. int main(){
  37. sci(t);
  38. while(t--){
  39. sci(n);
  40. vector<int>now(n);
  41. iota(now.begin(),now.end(),1);
  42. rep(i,1,n){
  43. rep(j,i,n){
  44. dp[i][j]=-1;
  45. }
  46. }
  47. while(SZ(now)>1){
  48. int dis=n,p=-1,sz=SZ(now)-1;
  49. rep(i,0,sz-1){
  50. int w=now[i+1]-now[i];
  51. if(w<dis)dis=w,p=i;
  52. }
  53. int x=cal(now[p],now[p+1]),y=cal(now[p],now[p+1]-1);
  54. if(x==y)now.erase(now.begin()+p);
  55. else now.erase(now.begin()+(p+1));
  56. }
  57. out(now[0]);
  58. }
  59. return 0;
  60. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/1003957
推荐阅读
相关标签
  

闽ICP备14008679号