bzoj 3489: A simple rmq problem k-dtree
阿新 • • 發佈:2018-12-11
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
分析: 對於每個數維護一個和。 表示前一個相同的數的下一個位置(沒有為),後一個相同數的前一個位置(沒有為)。 對於一個詢問,那麼一個數有貢獻,當且僅當 貢獻為。 直接k-dtree即可。
程式碼:
/************************************************************** Problem: 3489 User: liangzihao Language: C++ Result: Accepted Time:17156 ms Memory:472028 kb ****************************************************************/ #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> const int maxn=1e5+7; using namespace std; int n,cnt,root,x,y,lastans,m; int a[maxn],last[maxn],next[maxn],ls[maxn],top[maxn]; struct rec{ int d[3]; }; bool operator ==(rec a,rec b) { return (a.d[0]==b.d[0]) && (a.d[1]==b.d[1]) && (a.d[2]==b.d[2]); } struct node{ int l,r,data; }t[maxn*400]; void ins(int &p,rec l,rec r,rec d,int k,int op) { if (!p) p=++cnt; t[p].data=max(t[p].data,k); if (l==r) return; int mid=(l.d[op]+r.d[op])/2; rec L=l,R=r; L.d[op]=mid+1,R.d[op]=mid; if (d.d[op]<=mid) ins(t[p].l,l,R,d,k,(op+1)%3); else ins(t[p].r,L,r,d,k,(op+1)%3); } void query(int p,rec l,rec r,rec a,rec b,int op) { if ((l==a) && (r==b)) lastans=max(lastans,t[p].data); if (lastans>=t[p].data) return; int mid=(l.d[op]+r.d[op])/2; rec L=l,R=r; L.d[op]=mid+1,R.d[op]=mid; int tmp=0; if (b.d[op]<=mid) query(t[p].l,l,R,a,b,(op+1)%3); else if (a.d[op]>mid) query(t[p].r,L,r,a,b,(op+1)%3); else { rec A=a,B=b; A.d[op]=mid+1; B.d[op]=mid; query(t[p].l,l,R,a,B,(op+1)%3); query(t[p].r,L,r,A,b,(op+1)%3); } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { last[i]=1; next[i]=n; } for (int i=1;i<=n;i++) { scanf("%d",&a[i]); last[i]=ls[a[i]]+1; next[ls[a[i]]]=i-1; ls[a[i]]=i; } for (int i=1;i<=n;i++) { ins(root,(rec){{1,1,1}},(rec){{n,n,n}},(rec){{last[i],i,next[i]}},a[i],0); } for (int i=1;i<=m;i++) { int X,Y; scanf("%d%d",&X,&Y); x=min((X+lastans)%n+1,(Y+lastans)%n+1); y=max((X+lastans)%n+1,(Y+lastans)%n+1); lastans=0; query(root,(rec){{1,1,1}},(rec){{n,n,n}},(rec){{1,x,y}},(rec){{x,y,n}},0); printf("%d\n",lastans); } }