CodeForces - 1000F One Occurrence (主席树)
Posted asdfsag
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1000F One Occurrence (主席树)相关的知识,希望对你有一定的参考价值。
题意:从数组a中找出一个区间[l,r]中只出现过一次的数
设pre[i]表示a[i]在i之前的上一次出现,a[i]在[l,r]中只出现过一次等价于pre[i]<l,所以只需在[l,r]中找出一个满足pre[i]<l的i就行了。由于还必须保证i是在[l,r]中最后一次出现,一棵线段树是实现不了的,需要用主席树。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=5e5+10,mod=1e9+7,inf=0x3f3f3f3f; 5 int a[N],n,m,la[N],mi[N*40],ls[N*40],rs[N*40],tot,rt[N]; 6 #define l(u) ls[u] 7 #define r(u) rs[u] 8 #define mid ((l+r)>>1) 9 int cpy(int v) {int u=++tot; l(u)=l(v),r(u)=r(v),mi[u]=mi[v]; return u;} 10 void pu(int u) {mi[u]=min(mi[l(u)],mi[r(u)]);} 11 void upd(int& u,int v,int p,int x,int l=1,int r=n) { 12 u=cpy(v); 13 if(l==r) {mi[u]=x; return;} 14 p<=mid?upd(l(u),l(v),p,x,l,mid):upd(r(u),r(v),p,x,mid+1,r); 15 pu(u); 16 } 17 int qry(int u,int L,int R,int l=1,int r=n) { 18 if(l>R||r<L||mi[u]>=L)return 0; 19 if(l==r)return l; 20 int t=qry(l(u),L,R,l,mid); 21 return t?t:qry(r(u),L,R,mid+1,r); 22 } 23 int main() { 24 mi[0]=inf; 25 scanf("%d",&n); 26 for(int i=1; i<=n; ++i)scanf("%d",&a[i]); 27 for(int i=1; i<=n; ++i) { 28 rt[i]=rt[i-1]; 29 if(la[a[i]])upd(rt[i],rt[i],la[a[i]],inf); 30 upd(rt[i],rt[i],i,la[a[i]]); 31 la[a[i]]=i; 32 } 33 for(scanf("%d",&m); m--;) { 34 int l,r; 35 scanf("%d%d",&l,&r); 36 printf("%d ",a[qry(rt[r],l,r)]); 37 } 38 return 0; 39 }
以上是关于CodeForces - 1000F One Occurrence (主席树)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 1000F One Occurrence 主席树|| 离线+线段树
CodeForces - 1000F One Occurrence (主席树)
CodeForces - 1000F One Occurrence (主席树)