1. 程式人生 > >bzoj3489 A simple rmq problem

bzoj3489 A simple rmq problem

mat truct mod pen char ios spa ace 上一個

Description

因為是OJ上的題,就簡單點好了。給出一個長度為n的序列,給出M個詢問:在[l,r]之間找到一個在這個區間裏只出現過一次的數,並且要求找的這個數盡可能大。如果找不到這樣的數,則直接輸出0。我會采取一些措施強制在線。

Input

第一行為兩個整數N,M。M是詢問數,N是序列的長度(N<=100000,M<=200000)

第二行為N個整數,描述這個序列{ai},其中所有1<=ai<=N

再下面M行,每行兩個整數x,y,

詢問區間[l,r]由下列規則產生(OIER都知道是怎樣的吧>_<):

l=min((x+lastans)mod n+1,(y+lastans)mod n+1);

r=max((x+lastans)mod n+1,(y+lastans)mod n+1);

Lastans表示上一個詢問的答案,一開始lastans為0

Output

一共M行,每行給出每個詢問的答案。

Sample Input

10 10
6 4 9 10 9 10 9 4 10 4
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9

Sample Output

4
10
10
0
0
10
0
4
0
4

HINT

註意出題人為了方便,input的第二行最後多了個空格。

2015.6.24新加數據一組,2016.7.9放至40S,600M,但未重測

正解:$kd-tree$。

其實這題正解應該是主席樹套什麽鬼東西,然而我不會,於是還是上清新的$kd-tree$。。

我們求出每個點,上一個與它相同的點的位置$lst[i]$,下一個與它相同的點的位置$nxt[i]$。

那麽很容易發現,我們要滿足$3$個條件,即$l<=i<=r,lst[i]<l,r<nxt[i]$。

那麽我們直接構造一個以$i,lst[i],nxt[i]$為坐標的點的三維$kd-tree$,查詢的時候判斷一下就行了。

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5
#include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (200010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define fi02() for (RG int i=0;i<=2;++i) 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int pos[N],lst[N],nxt[N],a[N],K,n,m,l,r,rt,ans; 24 25 struct node{ 26 int a[3],mn[3],mx[3],l,r,v,sum; 27 28 bool operator < (const node &t) const{ 29 return a[K]<t.a[K]; 30 } 31 32 }t[N]; 33 34 il int gi(){ 35 RG int x=0,q=1; RG char ch=getchar(); 36 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 37 if (ch==-) q=-1,ch=getchar(); 38 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 39 return q*x; 40 } 41 42 il void merge(RG int x){ 43 fi02(){ 44 if (t[x].l){ 45 t[x].mn[i]=min(t[x].mn[i],t[t[x].l].mn[i]); 46 t[x].mx[i]=max(t[x].mx[i],t[t[x].l].mx[i]); 47 } 48 if (t[x].r){ 49 t[x].mn[i]=min(t[x].mn[i],t[t[x].r].mn[i]); 50 t[x].mx[i]=max(t[x].mx[i],t[t[x].r].mx[i]); 51 } 52 } 53 t[x].sum=max(t[t[x].l].sum,t[t[x].r].sum); 54 t[x].sum=max(t[x].sum,t[x].v); return; 55 } 56 57 il int build(RG int l,RG int r,RG int p){ 58 RG int mid=(l+r)>>1; K=p,nth_element(t+l,t+mid,t+r+1); 59 fi02() t[mid].mn[i]=t[mid].mx[i]=t[mid].a[i]; 60 if (l<mid) t[mid].l=build(l,mid-1,(p+1)%3); 61 if (r>mid) t[mid].r=build(mid+1,r,(p+1)%3); 62 merge(mid); return mid; 63 } 64 65 il int ca(node S){ return l<=S.mn[0] && S.mx[0]<=r && S.mx[1]<l && S.mn[2]>r; } 66 67 il int cb(node S){ 68 if (S.mn[1]>=l) return 0; if (S.mx[2]<=r) return 0; 69 if (S.mn[0]>r || S.mx[0]<l) return 0; return 1; 70 } 71 72 il void query(RG int x){ 73 if (l<=t[x].a[0] && t[x].a[0]<=r && t[x].a[1]<l && t[x].a[2]>r) ans=max(ans,t[x].v); 74 if (t[t[x].l].sum>t[t[x].r].sum){ 75 if (t[x].l){ 76 if (ca(t[t[x].l])) ans=max(ans,t[t[x].l].sum); 77 else if (cb(t[t[x].l]) && ans<t[t[x].l].sum) query(t[x].l); 78 } 79 if (t[x].r){ 80 if (ca(t[t[x].r])) ans=max(ans,t[t[x].r].sum); 81 else if (cb(t[t[x].r]) && ans<t[t[x].r].sum) query(t[x].r); 82 } 83 } else{ 84 if (t[x].r){ 85 if (ca(t[t[x].r])) ans=max(ans,t[t[x].r].sum); 86 else if (cb(t[t[x].r]) && ans<t[t[x].r].sum) query(t[x].r); 87 } 88 if (t[x].l){ 89 if (ca(t[t[x].l])) ans=max(ans,t[t[x].l].sum); 90 else if (cb(t[t[x].l]) && ans<t[t[x].l].sum) query(t[x].l); 91 } 92 } 93 return; 94 } 95 96 il void work(){ 97 n=gi(),m=gi(); 98 for (RG int i=1;i<=n;++i){ 99 a[i]=gi(),lst[i]=pos[a[i]]; 100 nxt[pos[a[i]]]=i,pos[a[i]]=i; 101 } 102 for (RG int i=1;i<=n;++i){ 103 if (!nxt[i]) nxt[i]=n+1; t[i].sum=t[i].v=a[i]; 104 t[i].a[0]=i,t[i].a[1]=lst[i],t[i].a[2]=nxt[i]; 105 } 106 rt=build(1,n,0); 107 while (m--){ 108 l=(gi()+ans)%n+1,r=(gi()+ans)%n+1,ans=0; 109 if (l>r) swap(l,r); query(rt),printf("%d\n",ans); 110 } 111 return; 112 } 113 114 int main(){ 115 File("rmq"); 116 work(); 117 return 0; 118 }

bzoj3489 A simple rmq problem