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
分析:
对于每个数维护一个
l
a
s
t
i
last_i
lasti和
n
e
x
t
i
next_i
nexti。
l
a
s
t
i
last_i
lasti表示前一个相同的数的下一个位置(没有为
1
1
1),
n
e
x
t
i
next_i
nexti后一个相同数的前一个位置(没有为
n
n
n)。
对于一个询问
(
l
,
r
)
(l,r)
(l,r),那么一个数有贡献,当且仅当
l
a
s
t
i
<
=
l
<
=
i
<
=
r
<
=
n
e
x
t
i
last_i<=l<=i<=r<=next_i
lasti<=l<=i<=r<=nexti
贡献为
a
i
a_i
ai。
直接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);
}
}