SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)
Posted Blackops
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)相关的知识,希望对你有一定的参考价值。
DQUERY - D-query
English | Vietnamese |
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
题目链接:SPOJ 3267
假设数组从1开始,以当前数字的位置(下标)为pos,贡献为1,用主席树维护前缀序列[1,i]的贡献和,则显然第i棵线段树就是对应的前缀序列[1,i],题目给出l与r,r可直接用,显然l还不对需要转换,我这里写的和其他人的做法不太一样,还是用区间内的区间求和思想。即对root[l-1]~root[r]求l~r的区间和。因为用的是下标而不是原值更不是离散化之后的值作插入位置,因此l,r既是询问区间也是求和区间。一开始范围搞错了把离散化之后的size作为值域大小,wa数次……,此外这题似乎还可以莫队或者离线树状数组搞搞,前者太模版了就懒的写了3W的数据量估计是可以莫队暴力过的,后者……理解不够深入就先不贴代码了
代码:
#include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) typedef pair<int,int> pii; typedef long long LL; const double PI=acos(-1.0); const int N=30010; struct seg { int lson,rson; int cnt; }; seg T[N*20]; int root[N],tot; vector<int>pos; int arr[N]; int last_pos[N]; void init() { pos.clear(); CLR(root,0); tot=0; T[0].cnt=T[0].lson=T[0].rson=0; CLR(last_pos,0); } void update(int &cur,int ori,int l,int r,int pos,int flag) { cur=++tot; T[cur]=T[ori]; T[cur].cnt+=flag; if(l==r) return ; int mid=MID(l,r); if(pos<=mid) update(T[cur].lson,T[ori].lson,l,mid,pos,flag); else update(T[cur].rson,T[ori].rson,mid+1,r,pos,flag); } int query(int S,int E,int l,int r,int x,int y) { if(x<=l&&r<=y) return T[E].cnt-T[S].cnt; else { int mid=MID(l,r); if(y<=mid) return query(T[S].lson,T[E].lson,l,mid,x,y); else if(x>mid) return query(T[S].rson,T[E].rson,mid+1,r,x,y); else return query(T[S].lson,T[E].lson,l,mid,x,mid)+query(T[S].rson,T[E].rson,mid+1,r,mid+1,y); } } int main(void) { int n,m,i,l,r; while (~scanf("%d",&n)) { init(); for (i=1; i<=n; ++i) { scanf("%d",&arr[i]); pos.push_back(arr[i]); } scanf("%d",&m); sort(pos.begin(),pos.end()); pos.erase(unique(pos.begin(),pos.end()),pos.end()); int temp_rt=0; for (i=1; i<=n; ++i) { arr[i]=lower_bound(pos.begin(),pos.end(),arr[i])-pos.begin()+1; if(!last_pos[arr[i]]) { update(root[i],root[i-1],1,n,i,1); last_pos[arr[i]]=i; } else { update(temp_rt,root[i-1],1,n,last_pos[arr[i]],-1); update(root[i],temp_rt,1,n,i,1); last_pos[arr[i]]=i; } } for (i=0; i<m; ++i) { scanf("%d%d",&l,&r); printf("%d\n",query(root[l-1],root[r],1,n,l,r)); } } return 0; }
以上是关于SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)的主要内容,如果未能解决你的问题,请参考以下文章