The scan sequence establishes a sustainable line segment tree.
Create a chairperson tree for each pos. pos corresponds to the position of single point modification, find +=val;
If it does not appear, assign the current position to find it. Otherwise, first subtract the contribution of the last number from root[i-1], and then add the contribution of this number.
At the same time, the last occurrence position of each element is maintained.
When querying: each chairperson tree maintains how many different numbers from 1 to i (current position) are.
When you find it, look for it in root [r]. The interval number in the tree >=l is the contribution of l~r in 1-r.
Understand that you can simulate the sample with the code.
#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;
}