SP3267 DQUERY-D-query (Encuentre el número de números diferentes en la práctica del asesor de intervalos en línea)

La secuencia de exploración establece un árbol de segmento de línea sostenible.

Cree un árbol de presidente para cada pos. pos corresponde a la posición de modificación de un solo punto, encuentra + = val;

Si no aparece, asigne la posición actual para encontrarlo. De lo contrario, primero resta la contribución del último número de la raíz [i-1] y luego suma la contribución de este número.

Al mismo tiempo, se mantiene la última posición de ocurrencia de cada elemento.

Al consultar: cada árbol de presidente mantiene cuántos números diferentes del 1 al i (posición actual) son.

Cuando lo encuentre, búsquelo en la raíz [r]. El número de intervalo en el árbol> = l es la contribución de l ~ r en 1-r.

Comprenda que puede simular la muestra con el código. 

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=30010;
typedef long long LL;
struct Tree{
    LL lson,rson,sum;
}tree[maxn<<5];
LL a[maxn],last[1000010],root[maxn];///数据还比较小不用离散化
LL tot=0;
void push_up(LL p){
    tree[p].sum=tree[tree[p].lson].sum+tree[tree[p].rson].sum;
}
///权值线段树也是线段树,不过是对每个区间对应的位置+1,同样可以push_up
LL update(LL pre,LL l,LL r,LL pos,LL val){
    LL rt=++tot;
    tree[rt].sum=tree[pre].sum;///新建点先附着上一个信息
    tree[rt].lson=tree[pre].lson;
    tree[rt].rson=tree[pre].rson;
    if(l==r) {///叶子节点进行单点修改
        tree[rt].sum+=val;
        return rt;
    }
    LL mid=(l+r)>>1;

    if(pos<=mid) tree[rt].lson=update(tree[pre].lson,l,mid,pos,val);
    else tree[rt].rson=update(tree[pre].rson,mid+1,r,pos,val);
    push_up(rt);
    return rt;
}
///查询>=l区间的区间总和
LL query(LL l,LL r,LL rt,LL pos){
    if(l==r) return tree[rt].sum;
    LL mid=(l+r)>>1;
    if(pos<=mid) return tree[tree[rt].rson].sum+query(l,mid,tree[rt].lson,pos);
    else return query(mid+1,r,tree[rt].rson,pos);
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  for(LL i=1;i<=n;i++){
    cin>>a[i];
  }
  for(LL i=1;i<=n;i++){
     if(!last[a[i]]){
        last[a[i]]=i;
        root[i]=update(root[i-1],1,n,i,1);
     }
     else{
        LL tmp=update(root[i-1],1,n,last[a[i]],-1);
        root[i]=update(tmp,1,n,i,1);
        last[a[i]]=i;
     }
  }
  LL Q;cin>>Q;
  while(Q--){
    LL l,r;cin>>l>>r;
    cout<<query(1,n,root[r],l)<<endl;
  }
return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/110358565
Recomendado
Clasificación