CF1000F One Occurrence (线段树)

 

time limit per test

3 seconds

memory limit per test

768 megabytes

You are given an array aa consisting of nn integers, and qq queries to it. ii -th query is denoted by two integers lili and riri . For each query, you have to find any integer that occurs exactly once in the subarray of aa from index lili to index riri (a subarray is a contiguous subsegment of an array). For example, if a=[1,1,2,3,2,4]a=[1,1,2,3,2,4] , then for query (li=2,ri=6)(li=2,ri=6) the subarray we are interested in is [1,2,3,2,4][1,2,3,2,4] , and possible answers are 11 , 33 and 44 ; for query (li=1,ri=2)(li=1,ri=2) the subarray we are interested in is [1,1][1,1] , and there is no such element that occurs exactly once.

Can you answer all of the queries?

Input

The first line contains one integer nn (1≤n≤5⋅1051≤n≤5⋅105 ).

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤5⋅1051≤ai≤5⋅105 ).

The third line contains one integer qq (1≤q≤5⋅1051≤q≤5⋅105 ).

Then qq lines follow, ii -th line containing two integers lili and riri representing ii -th query (1≤li≤ri≤n1≤li≤ri≤n ).

Output

Answer the queries as follows:

If there is no integer such that it occurs in the subarray from index lili to index riri exactly once, print 00 . Otherwise print any such integer.

Example

Input

Copy

6
1 1 2 3 2 4
2
2 6
1 2

Output

Copy

4
0

题解:

朴素的想法,对于[ L , R ] 我们应该找每个元素的最近的相同元素 pre,即区间最小的pre值,若min{pre} < L 则合法很容易想到线段树。

但 2[1 1 2 2 3 ]时对于区间第一个2的pre在区间外 ,对于这种情况我们发现只有最后一个2有影响。我们可以把pre设成inf

线段树的操作 单点修改,查询区间最小值。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define pa pair<int,int>
using namespace std;
const int N=5e5+10;
const int inf=1e18;
struct node{int x,y,i;}q[N];
int a[N],pre[N],temp[N],s[N];
pa mn[N<<2];
int n,m;
inline int ls(int p){return p<<1;}
inline int rs(int p){return p<<1|1;}
inline void update(int p){mn[p]=min(mn[ls(p)],mn[rs(p)]);}
bool cmp(node a,node b){return a.y==b.y?a.x<b.x:a.y<b.y;}
inline int rd(){
	int x=0;int f=1;char s=getchar();
	while(s>'9' || s<'0') if(s=='-')f=-1,s=getchar();
	while(s>='0' && s<='9') x=x*10+s-'0',s=getchar();
	return  x*f;
} 
void change(int p,int l,int r,int x,int val){
	if(x<=l && r<=x){mn[p]=make_pair(val,a[x]);return ;}
	int mid=(l+r)>>1;
	if(x<=mid) change(ls(p) , l   ,mid ,x,val);
	if(mid<x)  change(rs(p) ,mid+1,  r ,x,val); 
	update(p); 
}
pa query(int p,int l,int r,int x,int y){
	if(x<=l && r<=y){return mn[p];}
	int mid=(l+r)>>1;pa ans=make_pair(inf,0);
	if(x<=mid) ans=query(ls(p) ,l ,mid,x,y);
	if(mid<y)  ans=min(ans,query(rs(p),mid+1,r,x,y));
	return ans;
}
int main(){
//	freopen("F.in","r",stdin);
	n=rd();
	for(int i=1;i<=n;i++) a[i]=rd(),pre[i]=temp[a[i]],temp[a[i]]=i;
	m=rd();
	for(int i=1;i<=m;i++) q[i].x=rd(),q[i].y=rd(),q[i].i=i;
	sort(q+1,q+m+1,cmp); 
	for(int i=1,j=1;i<=m;i++){
		for(;j<=q[i].y && j<=n;j++){
			if(pre[j]) change(1,1,n,pre[j],inf);
			change(1,1,n,j,pre[j]);
		}
		pa ans=query(1,1,n,q[i].x,q[i].y);
		if(ans.first<q[i].x) s[q[i].i]=ans.second;
	}
	for(int i=1;i<=m;i++) printf("%d\n",s[i]);
	return 0;
} 

 

转载于:https://www.cnblogs.com/Exception2017/p/10252107.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值