3489: A simple rmq problem
Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1761 Solved: 592
[ Submit][ Status][ Discuss]
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
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
10
10
0
0
10
0
4
0
4
HINT
注意出题人为了方便,input的第二行最后多了个空格。
2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
#define max(a,b) ((a) > (b) ? (a) : (b))
using namespace std;
const int maxn = 1E5 + 10;
const int N = 300;
const int T = 4;
int n,m,cnt,LastAns,ans,A[maxn],last[maxn],L[maxn],R[maxn],rt[maxn*T],ma[maxn*T]
,lc[maxn*N],rc[maxn*N],Max[maxn*N],ma_son[maxn*N],Ans[maxn*2],ll[maxn*2],rr[maxn*2];
inline void query(int o,int l,int r,int pos)
{
ans = max(ans,Max[o]);
if (ma_son[o] <= ans) return; if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid) query(lc[o],l,mid,pos);
else query(rc[o],mid+1,r,pos);
}
inline void Query(int o,int l,int r,int ql,int qr)
{
if (ma[o] <= ans) return; query(rt[o],1,n,qr);
if (l == r) return; int mid = l + r >> 1;
if (ql <= mid) Query(o<<1,l,mid,ql,qr);
else Query(o<<1|1,mid+1,r,ql,qr);
}
inline void insert(int &o,int l,int r,int ql,int qr,int k)
{
if (!o) o = ++cnt; ma_son[o] = max(ma_son[o],k);
if (ql <= l && r <= qr) {Max[o] = max(Max[o],k); return;}
int mid = l + r >> 1;
if (ql <= mid) insert(lc[o],l,mid,ql,qr,k);
if (qr > mid) insert(rc[o],mid+1,r,ql,qr,k);
}
inline void Insert(int o,int l,int r,int x,int y,int z,int k)
{
ma[o] = max(ma[o],k);
if (x <= l && r <= y) {insert(rt[o],1,n,y,z,k); return;}
int mid = l + r >> 1;
if (x <= mid) Insert(o<<1,l,mid,x,y,z,k);
if (y > mid) Insert(o<<1|1,mid+1,r,x,y,z,k);
}
inline int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) A[i] = getint();
for (int i = 1; i <= n; i++)
L[i] = last[A[i]],last[A[i]] = i;
for (int i = 1; i <= n; i++) last[i] = n + 1;
for (int i = n; i; i--)
R[i] = last[A[i]],last[A[i]] = i;
for (int i = 1; i <= n; i++)
Insert(1,1,n,L[i] + 1,i,R[i] - 1,A[i]);
//cerr << (double)(clock()) / CLOCKS_PER_SEC << endl;
//cout << cnt << endl;
for (int i = 1; i <= m; i++)
{
int l = getint(),r = getint();
l = (l + LastAns) % n + 1;
r = (r + LastAns) % n + 1; if (l > r) swap(l,r);
//printf("%d\n",LastAns = Query(1,1,n,l,r));
ans = 0; Query(1,1,n,l,r); printf("%d\n",LastAns = ans);
//printf("%d : ",i); puts(LastAns == Ans[i] ? "Accepted" : "WrongAnswer");
}
//cerr << (double)(clock()) / CLOCKS_PER_SEC << endl;
return 0;
}