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;
}