主席树|线段树(区间不同的数的个数)spoj3267
2014-09-18 13:22
471 查看
3267. D-query
Problem code: DQUERY
EnglishVietnamese
Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the
subsequence ai, ai+1, ..., aj.
Input
Line 1: n (1 ≤ n ≤ 30000).Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.Example
Input 5 1 1 2 1 3 3 1 5 2 4 3 5 Output 3 2 3
首先是线段树解法,跟hdu上的几个题是一样的
#include<stdio.h> #include<algorithm> #include<string.h> #include<map> #define N 35000 #define M 250000 using namespace std; struct node { int x,y,id; }b[M]; int c ,ans[M],a ; map<int ,int >ma; bool cmp(node a,node b) { return a.y<b.y; } int lowbit(int x) { return x&(-x); } void update(int x,int val) { while(x<=N) { c[x]+=val; x+=lowbit(x); } } int sum(int x) { int s=0; while(x) { s+=c[x]; x-=lowbit(x); } return s; } int main() { int n,i,m,pre,j; //freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d%d",&b[i].x,&b[i].y); b[i].id=i; } sort(b,b+m,cmp); pre=1; memset(c,0,sizeof(c)); for(i=0;i<m;i++) { for(j=pre;j<=b[i].y;j++) { if(ma.find(a[j])==ma.end()) update(j,1); else { update(ma[a[j]],-1); update(j,1); } ma[a[j]]=j; } ans[b[i].id]=sum(b[i].y)-sum(b[i].x-1); pre=b[i].y+1; } for(i=0;i<m;i++) printf("%d\n",ans[i]); } return 0; }
然后是主席树,主席树保存前缀1...i出现在1...n的数有多少
查询的时候对于(l,r),之需要查询T[r]这个数,1...l有多少个不同的数,然后用总数减掉就可以了
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #include<algorithm> using namespace std; const int maxn=30010; const int maxm=maxn*100; int n,q,m,num; int a[maxn]; int cnt[maxm],lson[maxm],rson[maxm]; int T[maxm]; map<int,int> vis; int build(int l,int r) { int root=num++; cnt[root]=0; if(l!=r) { int mid=(l+r)>>1; lson[root]=build(l,mid); rson[root]=build(mid+1,r); } return root; } int update(int root,int pos,int val) { int newroot=num++,tmp=newroot; int l=1,r=n; cnt[newroot]=cnt[root]+val; while(l<r) { int mid=(l+r)>>1; if(pos<=mid) { r=mid; lson[newroot]=num++,rson[newroot]=rson[root]; newroot=lson[newroot],root=lson[root]; } else { l=mid+1; rson[newroot]=num++;lson[newroot]=lson[root]; newroot=rson[newroot],root=rson[root]; } cnt[newroot]=cnt[root]+val; } return tmp; } int query(int root,int pos) { int l=1,r=n,ans=0; while(pos>l) { int mid=(l+r)>>1; if(pos<=mid) { r=mid; root=lson[root]; } else { l=mid+1; ans+=cnt[lson[root]]; root=rson[root]; } } return ans; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++)scanf("%d",&a[i]); scanf("%d",&q); num=0; vis.clear(); T[0]=build(1,n); for(int i=1;i<=n;i++) { if(vis.count(a[i])) { int tmp=update(T[i-1],vis[a[i]],-1); T[i]=update(tmp,i,1); } else { T[i]=update(T[i-1],i,1); } vis[a[i]]=i; } while(q--) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",cnt[T[r]]-query(T[r],l)); } } return 0; }
相关文章推荐
- 主席树-查询区间有多少个不同的数
- SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)
- hdu 3333 Turing Tree(线段树求区间内不同值之和+离线处理)
- POJ2104-K-th Number-区间第k大-可持久化线段树/主席树
- POJ 2528——Mayor's posters——————【线段树区间替换、找存在的不同区间】
- hdu 5919 主席树(区间不同数个数+区间第k个数)
- 【bzoj4571: [Scoi2016]美味】区间异或和最大 ,可持久化线段树(主席树)
- hdu5919 主席树求区间不同数
- SPOJ - DQUERY 主席树求区间中不同数字的个数
- SPOJ3267 D-Query 树状数组离线操作 或 主席树 查询某一区间内有多少不同的数
- Hdu-5919 Sequence II(主席树在线求区间不同数)
- SPOJ DQUERY (主席树求区间不同数个数)
- spoj3267 D-query 主席树(可持久化线段树)
- hdu 3333 Turing Tree 线段树 离线查询(区间内不同的数之和)
- hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)
- spoj DQUERY - D-query(区间不同数的个数 主席树 or BIT)
- SPOJ-DQUERY - D-query (主席树 区间不同数个数)
- 线段树(待续)(区间每个数加上不同的斐波那契额数)Codeforces Round #FF (Div. 2)E
- 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)
- SPOJ DQUERY 区间内不同数的个数 主席树