和hdu3333基本一样 两种方法
主席树有时可看做是利用线段树做的一个前缀 但在这里并没有用到前缀和的性质 和线段树离线做法有些类似 都是把同一个数出现的位置尽量提前
#include <bits/stdc++.h>
using namespace std;
struct node
{
int nl;
int nr;
int val;
};
node tree[1000010];
int num[30010],root[30010],mp[1000010];
int n,m,tot;
int build(int l,int r)
{
int cur,m;
cur=tot++;
tree[cur].nl=0,tree[cur].nr=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].nl=build(l,m);
tree[cur].nr=build(m+1,r);
return cur;
}
int update(int rot,int tar,int val,int l,int r)
{
int cur,m;
cur=tot++;
tree[cur]=tree[rot];
tree[cur].val+=val;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].nl=update(tree[cur].nl,tar,val,l,m);
else tree[cur].nr=update(tree[cur].nr,tar,val,m+1,r);
return cur;
}
int query(int rot,int pl,int pr,int l,int r)
{
int res,m;
if(pl<=l&&r<=pr)
{
return tree[rot].val;
}
res=0,m=(l+r)/2;
if(pl<=m) res+=query(tree[rot].nl,pl,pr,l,m);
if(pr>m) res+=query(tree[rot].nr,pl,pr,m+1,r);
return res;
}
int main()
{
int i,q,l,r;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
memset(mp,0,sizeof(mp));
tot=0;
root[0]=build(1,n);
for(i=1;i<=n;i++)
{
if(!mp[num[i]])
{
root[i]=update(root[i-1],i,1,1,n);
}
else
{
root[i]=update(root[i-1],mp[num[i]],-1,1,n);
root[i]=update(root[i],i,1,1,n);
}
mp[num[i]]=i;
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(root[r],l,n,1,n));
}
}
return 0;
}
还可以用线段树离线处理
#include <bits/stdc++.h>
using namespace std;
struct node1
{
int l;
int r;
int val;
};
struct node2
{
int l;
int r;
int id;
int val;
};
map <int,int> mp;
node1 tree[120010];
node2 order[200010];
int ary[30010];
int n,q;
bool cmpI(node2 n1,node2 n2)
{
return n1.r<n2.r;
}
bool cmpII(node2 n1,node2 n2)
{
return n1.id<n2.id;
}
void pushup(int cur)
{
tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}
void update(int tar,int val,int cur)
{
if(tree[cur].l==tree[cur].r)
{
tree[cur].val=val;
return;
}
if(tar<=tree[2*cur].r) update(tar,val,2*cur);
else update(tar,val,2*cur+1);
pushup(cur);
}
int query(int pl,int pr,int cur)
{
int res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
res=0;
if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}
int main()
{
int i,p;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&ary[i]);
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&order[i].l,&order[i].r);
order[i].id=i,order[i].val=0;
}
mp.clear();
build(1,n,1);
sort(order+1,order+q+1,cmpI);
p=1;
for(i=1;i<=q;i++)
{
while(p<=order[i].r)
{
if(mp[ary[p]]!=0) update(mp[ary[p]],0,1);
update(p,1,1);
mp[ary[p]]=p;
p++;
}
order[i].val=query(order[i].l,order[i].r,1);
}
sort(order+1,order+q+1,cmpII);
for(i=1;i<=q;i++)
{
printf("%d\n",order[i].val);
}
}
return 0;
}