您的位置:首页 > 产品设计 > UI/UE

SPOJ - DQUERY 主席树求区间中不同数字的个数

2016-11-04 18:34 543 查看
传送门:SPOJ - DQUERY

题目大意

给定一个序列,求然后有q次查询求[L,R]区间中不同数字的个数

解题思路

主席树模版类型题目,离散化,更新查询

AC代码

#include <cstdio>
#include <iostream>
#include <map>
using namespace std;
const int MX = 1e5+5;
const int N = MX*20;
int n,q,tot;
int A[MX];
int T
,lson
,rson
,sum
;

int build(int l,int r)
{
int rt = tot++;
sum[rt] = 0;
int mid = (l+r)>>1;
if(l!=r) {
lson[rt] = build(l,mid);
rson[rt] = build(mid+1,r);
}
return rt;
}
int update(int rt,int pos,int val)
{
int nrt = tot++;
int tmp = nrt;
int l=1,r=n;
sum[nrt] = sum[rt] + val;
while(l<r) {
int mid = (l+r)>>1;
if(pos<=mid) {
lson[nrt] = tot++;
rson[nrt] = rson[rt];
nrt = lson[nrt];
rt =  lson[rt];
r  = mid;
} else {
rson[nrt] = tot++;
lson[nrt] = lson[rt];
nrt = rson[nrt];
rt = rson[rt];
l = mid+1;
}
sum[nrt] = sum[rt]+val;
}
return tmp;
}
int query(int rt,int pos)
{
int  l= 1,r = n,ret = 0;
while(pos>l) {
int mid = (l+r)>>1;
if(pos>mid)  {
l = mid+1;
rt= rson[rt];
} else{
r  = mid;
ret += sum[rson[rt]];
rt  =  lson[rt];
}
}
return ret+sum[rt];
}

int main()
{freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&A[i]);
T[0] = build(1,n);
map<int,int>mp;
for(int i=1;i<=n;i++) {
if(mp.find(A[i])==mp.end()) T[i] =  update(T[i-1],i,1);
else {
int tmp  = update(T[i-1],mp[A[i]],-1);
T[i]  = update(tmp,i,1);
}
mp[A[i]] = i;
}
scanf("%d",&q);
while(q--)  {
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query(T[r],l));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: