码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces - 1000F One Occurrence (主席树)

时间:2020-05-10 19:04:24      阅读:50      评论:0      收藏:0      [点我收藏+]

标签:using   name   names   scanf   ++   实现   include   pre   min   

题意:从数组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\n",a[qry(rt[r],l,r)]);
37     }
38     return 0;
39 }

 

CodeForces - 1000F One Occurrence (主席树)

标签:using   name   names   scanf   ++   实现   include   pre   min   

原文地址:https://www.cnblogs.com/asdfsag/p/12864485.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!