[spoj D-query] 主席树求区间不同数
2016-10-20 11:10
627 查看
[spoj D-query] 主席树求区间不同数
题目链接:[spoj D-query]题意描述:给定N个数a1,a2,…,an,Q个询问。每次查询求区间中不同数的个数。(1≤N≤30000,1≤Q≤200000,1≤ai≤106,)
解题思路:用第i线段树来维护前i个数,从第j个数到第i个数的区间不同数(∀j,1≤j≤i)。那么根据第i棵树以及ai+1,求第i+1棵树的步骤如下:
如果ai+1在前面没有出现过,那么直接在i+1位置上+1;
如果在前面的第k位出现了,那么在k位置上−1,然后在i+1位置上+1;
#include <map> #include <set> #include <queue> #include <cmath> #include <cstdio> #include <string> #include <cstring> #include <iostream> #include <algorithm> using namespace std; //#pragma comment(linker, "/STACK:1024000000,1024000000") #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) #define fst first #define snd second #define __mid__ int mid = ((l + r) >> 1) //typedef __int64 LL; //typedef unsigned __int64 ULL; typedef pair<int, int> PII; const int MAXN = 30000 + 5; const int MX = 1e6 + 5; const int INF = 0x3f3f3f3f; int N, Q, A[MAXN], L, R; int TSZ; int root[MAXN]; int rec[MX]; struct TNode { int ls, rs, sum; } node[MAXN * 20]; int build(int l, int r) { int rt = TSZ ++; node[rt].sum = 0; if(l == r) { node[rt].ls = node[rt].rs = -1; return rt; } __mid__; node[rt].ls = build(l, mid); node[rt].rs = build(mid + 1, r); return rt; } int update(int pos, int v, int r1, int l, int r) { int r2 = TSZ ++; node[r2] = node[r1]; node[r2].sum += v; if(l == r) return r2; __mid__; if(pos <= mid) node[r2].ls = update(pos, v, node[r1].ls, l, mid); else node[r2].rs = update(pos, v, node[r1].rs, mid + 1, r); return r2; } int query(int pos, int rt, int l, int r) { if(l == r) return node[rt].sum; __mid__; if(pos <= mid) return query(pos, node[rt].ls, l, mid) + node[node[rt].rs].sum; else return query(pos, node[rt].rs, mid + 1, r); } int main() { #ifndef ONLINE_JUDGE FIN; #endif // ONLINE_JUDGE while(~scanf("%d", &N)) { for(int i = 1; i <= N; i++) scanf("%d", &A[i]); TSZ = 0; memset(rec, -1, sizeof(rec)); root[0] = build(1, N); for(int i = 1; i <= N; i++) { int& x = A[i]; if(rec[x] == -1) { root[i] = update(i, 1, root[i - 1], 1, N); } else { int temp = update(rec[x], -1, root[i - 1], 1, N); root[i] = update(i, 1, temp, 1, N); } rec[x] = i; } scanf("%d", &Q); while(Q --) { scanf("%d %d", &L, &R); int ans = query(L, root[R], 1, N); printf("%d\n", ans); } } return 0; }
相关文章推荐
- SPOJ DQUERY (主席树求区间不同数个数)
- SPOJ DQUERY 求区间内不同数的个数 主席树
- spoj D-query 区间不同数个数 主席树||离线+树状数组
- SPOJ DQUERY - D-query(主席树 ,求区间不同的数个数)
- SPOJ3267 D-Query 树状数组离线操作 或 主席树 查询某一区间内有多少不同的数
- SPOJ DQUERY - D-query(主席树-区间不同数的个数)
- SPOJ DQUERY 求区间内不同数的个数 (主席树)
- SPOJ-DQUERY-主席树求区间不同数个数模板
- SPOJ - DQUERY 主席树求区间中不同数字的个数
- SPOJ D-query 区间不同数的个数 [在线主席树 or 离线树状数组]
- spoj DQUERY - D-query(区间不同数的个数 主席树 or BIT)
- SPOJ-DQUERY - D-query (主席树 区间不同数个数)
- SPOJ:D-query(非常规主席树求区间不同数的个数)
- SPOJ D-query 主席树在线(求区间不同的数的个数)
- SPOJ DQUERY(树状数组离线处理 or 主席树 区间不同数个数)
- SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)
- SPOJ DQUERY 区间内不同数的个数 主席树
- SPOJ 3267. D-query (主席树,查询区间有多少个不相同的数)
- SPOJ - DQUERY D-query 离线+树状数组 (区间不同数的个数)
- SPOJ DQUERY 区间内不同数的个数