标签:nlogn key值 strong 下标 单点更新 using include 维护 print
题意:一个长度为n的序列(记为A[i]),q次查询,每次输出查询区间内任意一个只出现一次的数字,没有则输出0。
思路:线段树结点存元素的位置和上一个相同元素出现过的位置(没有则为0,记为pos),线段树维护区间结点最小值,结点封装在pair里,第一key值为前一个相同元素出现的位置,先将查询存下来,对于1到n的每一个前缀【1,r】,维护元素的最右边出现的pos值,例如1 1 2 3 2这个区间,他们的pos值分别是inf,1,inf,0,3。对于已经知道了【1,r】,要得到【1,r+1】,若A【r+1】在前面出现过,则将前面元素的pos值改为inf,再记录自己的pos值。
像1 1 2 3 2 加进来一个3 ,则pos值的变化为inf,1,inf,0,3—> inf,1,inf,inf,4。这个用线段树的单点更新维护,再将询问以右端点排序,从1开始枚举序列的右端点,若此时的右端点和询问的右端点一致,区间查询一次询问的区间,若得到的pos最小值比l小,代表这个数的上一个值出现的位置再区间外边,则这个数就是查询的答案了,若最小值不符合,则代表没有符合题意的数字。
AC代码:复杂度nlogn
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 using namespace std; 5 const int maxn=5e5+10,inf=0x3f3f3f3f; 6 typedef pair<int,int> pa; 7 int n,q; 8 int A[maxn],ans[maxn],pos[maxn]; 9 pa a[maxn<<2]; 10 11 struct Q{ 12 int l,r,id; 13 }p[maxn]; 14 15 void update(int pos,int val,int l,int r,int rt){ 16 if(l==r){ 17 a[rt].first=val; 18 a[rt].second=pos;//注意这里的pos值代表元素的下标 19 return; 20 } 21 int m=l+r>>1; 22 if(pos<=m) 23 update(pos,val,l,m,rt<<1); 24 else 25 update(pos,val,m+1,r,rt<<1|1); 26 a[rt]=min(a[rt<<1],a[rt<<1|1]); 27 } 28 29 pa query(int L,int R,int l,int r,int rt){ 30 if(L<=l&&r<=R){ 31 return a[rt]; 32 } 33 int m=l+r>>1; 34 pa z;z.first=inf; 35 if(L<=m) 36 z=min(z,query(L,R,l,m,rt<<1)); 37 if(R>m) 38 z=min(z,query(L,R,m+1,r,rt<<1|1)); 39 return z; 40 } 41 42 bool cmp(Q a,Q b){ 43 return a.r==b.r ? a.l<b.l : a.r < b.r; 44 } 45 46 int main(){ 47 scanf("%d",&n); 48 for(int i=1;i<=n;i++){ 49 scanf("%d",&A[i]); 50 } 51 cin>>q; 52 for(int i=1;i<=q;i++){ 53 scanf("%d%d",&p[i].l,&p[i].r); 54 p[i].id=i; 55 } 56 sort(p+1,p+1+q,cmp); 57 for(int i=1,j=1;i<=n;i++){ 58 if(pos[A[i]]) update(pos[A[i]],inf,1,n,1);//如果之前出现过,将之前出现数字的pos值改为inf 59 update(i,pos[A[i]],1,n,1);//更新现在的右端点值 60 for(;p[j].r==i;j++){ 61 pa now=query(p[j].l,p[j].r,1,n,1); 62 if(now.first<p[j].l){ 63 ans[p[j].id]=A[now.second]; 64 } 65 } 66 pos[A[i]]=i;//维护pos数组,pos【i】代表i数字上次出现的位置 67 } 68 for(int i=1;i<=q;i++){ 69 printf("%d\n",ans[i]); 70 } 71 return 0; 72 } 73 /* 74 6 75 1 1 2 2 3 3 76 1 77 1 3 78 */
标签:nlogn key值 strong 下标 单点更新 using include 维护 print
原文地址:https://www.cnblogs.com/qq2210446939/p/12146586.html