CF1000F One Occurrence 主席树 线段树

Posted bxd123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1000F One Occurrence 主席树 线段树相关的知识,希望对你有一定的参考价值。

题意:

给定一个长度为n序列,m个询问,每次询问给定一个区间[l,r],如果这个区间里存在只出现一次的数,输出这个数(如果有多个就输出任意一个),没有就输出0,n,m<=5*10^5

题解:

  •  考虑每个查询区间  维护数字上一个出现的位置 如果上一个出现的位置小于l 那么说明区间内只有一个数
  • 但是如果区间有两个相同的数字 可能左边的数字的上一个数字小于l   所以要消去其影响
  • 所以只要维护每个数字最右边数字的上一个数字出现的位置即可 可以在线用主席树来维护一个前缀和树  或者离线用线段树
技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+10;
struct node{int minn,num;}t[N<<6];
node merge(node a,node b)
{
    if(a.minn<b.minn)return (node){a.minn,a.num};
    else return (node){b.minn,b.num};
}
int lson[N<<6],rson[N<<6],n,m,last[N],pos[N],a[N],T[N],ncnt;
void build(int l,int r,int &pos)
{
    pos=++ncnt;
    if(l==r){t[pos]=(node){1000000000,0};return ;}
    int m=(l+r)>>1;
    build(l,m,lson[pos]);build(m+1,r,rson[pos]);
    t[pos]=merge(t[lson[pos]],t[rson[pos]]);
}
void upnode(int x,int v,int num,int l,int r,int pre,int &pos)
{
    pos=++ncnt;
    lson[pos]=lson[pre];
    rson[pos]=rson[pre];
    t[pos]=t[pre];
    if(l==r){t[pos]=(node){v,num};return ;}
    int m=(l+r)>>1;
    if(x<=m)upnode(x,v,num,l,m,lson[pre],lson[pos]);
    else upnode(x,v,num,m+1,r,rson[pre],rson[pos]);
    t[pos]=merge(t[lson[pos]],t[rson[pos]]);
}
node qmin(int L,int R,int l,int r,int pos)
{
    if(L<=l&&r<=R)return t[pos];
    node ans=(node){100000000,0};
    int m=(l+r)>>1;
    if(L<=m)ans=merge(ans,qmin(L,R,l,m,lson[pos]));
    if(R>m) ans=merge(ans,qmin(L,R,m+1,r,rson[pos]));
    return ans;
}
int main()
{
    cin>>n;node ans;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        last[i]=pos[a[i]];
        pos[a[i]]=i;
    }
    build(1,n,T[0]);
    for(int i=1;i<=n;i++)
    {    
        T[i]=T[i-1];
        upnode(i,last[i],a[i],1,n,T[i],T[i]);
        if(last[i])    
        {
            upnode(last[i],100000000,0,1,n,T[i],T[i]);
        }
    }
    cin>>m;int l,r;
    while(m--)
    {
        scanf("%d%d",&l,&r);
        ans=qmin(l,r,1,n,T[r]);
        if(ans.minn<l)printf("%d
",ans.num);
        else printf("0
");
    }
    return 0;
}
View Code

 

以上是关于CF1000F One Occurrence 主席树 线段树的主要内容,如果未能解决你的问题,请参考以下文章

F - One Occurrence CodeForces - 1000F (线段树+离线处理)

Codeforces 1000F One Occurrence 主席树|| 离线+线段树

CodeForces - 1000F One Occurrence (主席树)

CodeForces - 1000F One Occurrence (主席树)

One Occurrence 线段树离线维护最小值

主席树补充练习