[关闭]
@ysner 2018-09-29T17:09:18.000000Z 字数 2314 阅读 1885

[bzoj3489]A simple rmq problem

kd-tree


题面

给出一个长度为的序列,给出个询问:
之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。
如果找不到这样的数,则直接输出。我会采取一些措施强制在线。

解析

只出现过一次,就是上一次出现在位置之前,下一次出现在位置之后。
这个有点像三维偏序,但这里有一维是区间啊。
树套树续一下应该能过。

然而,对于维数较高的范围计数问题,是更佳选择。
其复杂度稳定为维数),而且空间线性。

一般框架:

对一个新加入的点,先自己更新自己的范围,再用儿子更新自己的范围。

把上一次,这一次,下一次这个数出现的位置看作三个维度就可以了。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define ls t[k].l
  11. #define rs t[k].r
  12. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  13. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  14. using namespace std;
  15. const int N=2e5+100;
  16. int n,m,b[N],R[N],L[N],now,app[N],rt,ans;
  17. il ll gi()
  18. {
  19. re ll x=0,t=1;
  20. re char ch=getchar();
  21. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  22. if(ch=='-') t=-1,ch=getchar();
  23. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  24. return x*t;
  25. }
  26. il void cmin(re int &x,re int y){x=min(x,y);}
  27. il void cmax(re int &x,re int y){x=max(x,y);}
  28. struct dat
  29. {
  30. int d[3],w,max;
  31. il bool operator < (const dat &o) const{return d[now]<o.d[now];}
  32. }a[N];
  33. struct node
  34. {
  35. dat a;
  36. int l,r,mn[3],mx[3];
  37. }t[N];
  38. struct kd_tree
  39. {
  40. il void upd(re int k,re int p)
  41. {
  42. fp(i,0,2) cmin(t[k].mn[i],t[p].mn[i]),cmax(t[k].mx[i],t[p].mx[i]);
  43. t[k].a.max=max(t[k].a.max,t[p].a.max);
  44. }
  45. il void pushup(re int k)
  46. {
  47. fp(i,0,2) t[k].mn[i]=t[k].mx[i]=t[k].a.d[i];
  48. if(ls) upd(k,ls);if(rs) upd(k,rs);
  49. }
  50. il void Build(re int &k,re int l,re int r,re int tag)
  51. {
  52. re int mid=l+r>>1;now=tag;
  53. nth_element(a+l,a+mid,a+r+1);k=mid;
  54. t[k].a=a[mid];
  55. if(l<mid) Build(ls,l,mid-1,(tag+1)%3);else ls=0;
  56. if(mid<r) Build(rs,mid+1,r,(tag+2)%3);else rs=0;
  57. pushup(k);
  58. }
  59. il void Query(re int k,re int l,re int r)
  60. {
  61. if(!k||t[k].a.max<ans) return;
  62. if(t[k].a.d[1]>=l&&t[k].a.d[1]<=r&&t[k].a.d[0]<l&&t[k].a.d[2]>r) ans=max(ans,t[k].a.w);
  63. if(t[k].mn[1]>=l&&t[k].mx[1]<=r&&t[k].mx[0]<l&&t[k].mn[2]>r) ans=max(ans,t[k].a.max);
  64. if(t[k].mn[1]>r||t[k].mx[1]<l||t[k].mn[0]>=l||t[k].mx[2]<=r) return;
  65. Query(ls,l,r);Query(rs,l,r);
  66. }
  67. }kd;
  68. int main()
  69. {
  70. n=gi();m=gi();
  71. fp(i,1,n) b[i]=gi(),L[i]=app[b[i]],app[b[i]]=i,R[i]=n+1;
  72. fp(i,0,n) app[i]=n+1;
  73. fq(i,n,1) R[i]=app[b[i]],app[b[i]]=i;
  74. fp(i,1,n) a[i].d[0]=L[i],a[i].d[1]=i,a[i].d[2]=R[i],a[i].max=a[i].w=b[i];
  75. kd.Build(rt,1,n,0);
  76. while(m--)
  77. {
  78. re int l=gi(),r=gi();
  79. l=(l+ans)%n+1,r=(r+ans)%n+1;
  80. if(l>r) swap(l,r);
  81. ans=0;kd.Query(rt,l,r);
  82. printf("%d\n",ans);
  83. }
  84. return 0;
  85. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注