• CodeForces


    题意:从数组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 }
  • 相关阅读:
    App如何选择移动广告平台,开发者2
    mouseover与mouseenter与mousemove差额mouseout与mouseleave差额
    JFinal 的源代码超具体的分析DB+ActiveRecord
    Vim经常使用技巧总结1
    2015第4周四网摘
    Java任务调度
    2015第4周二网摘
    2015第4周一
    2015第三周日
    转SpringSided代码规范遵循
  • 原文地址:https://www.cnblogs.com/asdfsag/p/12864485.html
Copyright © 2020-2023  润新知