2013 Asia Regional Contest Problem H --- Number Squence (树状数组 + 离线)
来源:互联网 发布:大连知行中学中考成绩 编辑:程序博客网 时间:2024/05/29 03:42
链接: http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1792
Description
Ikki最近又喜欢上了数列游戏,她现在想出个问题考考你,问题是这样的:
首先给你一个由n个整数组成的序列然后Ikki会给出一系列的提问:知道了区间的两个端点s和e,那么这个区间内有多少个不同的数字?
Input
多组测试数据,处理到文件结束,对于每组数据:
第一行输入两个整数n,q分别表示序列中数的个数和Ikki提问的次数
(0<n≤100000,0<q≤100000)。
第二行输入n个整数xi~xn表示序列中每个数的大小。(0 <= x <= 109 )
接下来的q行每行输入两个正整数a,b(a≤b)表示询问的区间为[a,b]。(序列下标从1开始)
Output
对于每组测试数据,输出q行依次表示每个提问的答案。
Sample Input
6 3
1 2 1 2 3 4
1 2
1 3
2 5
Sample Output
2
2
3
分析:
我们可以将查询区间按右端点排序,从左向右枚举i,维护一个树状数组,其中getsum(k)表示从k到i不同的数字有多少个,考虑到将第i个数字加入,这时候,树状数组里面发生改变的仅仅是
last[v] +1 到 i 这个区间的getsum()值,其中v是第i位数字,last[v]表示v这个数上次出线的位置,如果没有出现就为0。所以,我们把树状数组last[v]+1这个位置的值+1,把i+1这个位置的值-1,这样求和的时候,只要是左端点在last[v]+1之后的(包括自己),就能将v这点给包括进来了。然后枚举到i之后,我们考虑右端点是i的全部查询,对其左端点在树状数组中求和就可以了。
last[v] +1 到 i 这个区间的getsum()值,其中v是第i位数字,last[v]表示v这个数上次出线的位置,如果没有出现就为0。所以,我们把树状数组last[v]+1这个位置的值+1,把i+1这个位置的值-1,这样求和的时候,只要是左端点在last[v]+1之后的(包括自己),就能将v这点给包括进来了。然后枚举到i之后,我们考虑右端点是i的全部查询,对其左端点在树状数组中求和就可以了。
代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <ctime>#define MAXN 100005#define RST(N)memset(N, 0, sizeof(N))using namespace std;struct Node{ int l, r; int x;}q[MAXN];int n, Q, pre[1000001], val[MAXN], tre[MAXN];int tmp[MAXN], xu[MAXN], p[MAXN], res[MAXN], a, b;bool cmp(Node a, Node b) { return a.r < b.r; }inline int lowbit(int x) { return x & (-x); }void add(int pos, int x){ while(pos <= n) { tre[pos] += x; pos += lowbit(pos); }}int getsum(int pos){ int sum = 0; while (pos > 0) { sum += tre[pos]; pos -= lowbit(pos); } return sum;}int bin_search(int x){ int low = 1, high = n, mid; while(low <= high) { mid = (low + high) >> 1; if(tmp[mid] > x) high = mid - 1; else if(tmp[mid] < x) low = mid + 1; else return xu[mid]; }}void Init(){ sort(tmp+1, tmp+n+1); int m = 1; xu[1] = 1; for(int i=2; i<=n; i++) { if(xu[i] != xu[i-1]) xu[i] = ++m; else xu[i] = m; } for(int i=1; i<=n; i++) val[i] = bin_search(val[i]); RST(tre), RST(p);}void solve(int Q){ int m = 0; for(int i=1; i<=n; i++) { pre[i] = p[val[i]]; p[val[i]] = i; } for(int i=1; i<=n; i++) { add(pre[i]+1, 1); add(i+1, -1); while(m < Q && q[m].r == i) { res[q[m].x] = getsum(q[m].l); m++; } } for(int i=0; i<Q; i++) printf("%d\n",res[i]);}int main(){ while(~scanf("%d %d", &n, &Q)) { for(int i=1; i<=n; i++) { scanf("%d", &val[i]); tmp[i] = val[i]; xu[i] = i; } Init(); for(int i=0; i<Q; i++) { scanf("%d %d", &q[i].l, &q[i].r); q[i].x = i; } sort(q, q+Q, cmp); solve(Q); } return 0;}
0 0
- 2013 Asia Regional Contest Problem H --- Number Squence (树状数组 + 离线)
- ACM Asia Regional (Kanpur Site) Programming Contest 2001 Problem H
- hdu4788 水题 Hard Disk Drive (2013 Asia Chengdu Regional Contest problem H)
- hdu4786 Fibonacci Tree (2013 Asia Chengdu Regional Contest problem F)
- 2014 Asia Shanghai Regional Contest H
- Asia Regional Contest, Tokyo,Problem C Shopping
- 2013 Asia Chengdu Regional Contest
- 2013 Asia Hangzhou Regional Contest
- 2014-2015 ACM-ICPC, Asia Xian Regional Contest(H - The Problem to Make You Happy )
- 【树状数组】The 36th ACM/ICPC Asia Regional Beijing Site Online Contest - G Panda
- 2012 Asia ChangChun Regional Contest(2013区域赛练习)
- The 2014 ACM-ICPC Asia Mudanjiang Regional Contest - H
- 2015 ACM-ICPC Asia Amritapuri Regional Contest H
- 2014 Asia AnShan Regional Contest (dp)
- hdu4772 水题 Zhuge Liang's Password (2013 Asia Hangzhou Regional Contest problem C)
- hdu4771 BFS Stealing Harry Potter's Precious (2013 Asia Hangzhou Regional Contest problem B)
- hdu4770 暴力状压 Lights Against Dudely (2013 Asia Hangzhou Regional Contest problem A)
- hdu4452 搜索模拟 Running Rabbits (2012 Asia JinHua Regional Contest problem K)
- 消息系统该Push/Pull模式分析
- 图书管理系统(C++实践)
- 回到顶部
- HTML5 webSocket
- N个字符全排列的非递归实现
- 2013 Asia Regional Contest Problem H --- Number Squence (树状数组 + 离线)
- SQL Helper
- Virtualbox安装Ubuntu13.04并搭建Hadoop环境(单机模式+伪分布模式)
- php解析HTML
- java UDP聊天与文件传输
- NAT ip地址映射
- Multiple DataNodes on a single machine
- 基于MFC的简易计算器
- ios 谓词的使用