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 (主席树)

CF1000F One Occurrence 主席树 线段树

主席树补充练习

CodeForces - 1513C Add One