查询区间内不同数字的个数 lydsy1878
来源:互联网 发布:java证书有哪些 编辑:程序博客网 时间:2024/05/17 22:31
描述 :
HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。
Input
第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。 N<=50000 M<=200000
第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。 N<=50000 M<=200000
Output
M行,每行一个整数,依次表示询问对应的答案。
Sample Input
6
1 2 3 4 3 5
6
1 2 3 4 3 5
3
1 2
3 5
2 6
1 2
3 5
2 6
Sample Output
2
2
4
以上转自(大视野测评)
算法很机智,实现也很容易。是离线查询的思想。预处理:先将N个数字读取进来,用next[]数组储存每个数字下一次出现的位置,fir[i]布尔数组表示从当前查询的位置到结尾第i个元素是否为第一次出现,那么区间[1,x]的fir[i]的和即为这个区间的数的个数,用一个树状数组即可。再将M次查询读取进来,按查询区间的左端点进行排序,然后开始,遍历M个查询的左端点,将区间以前出现过的数字用next[]数组转移至左端点以后,这样区间[左端点的坐标,x]的fir[i]的和即为这个区间的数的个数。再对这个区间进行查询。时间复杂度:预处理O(N + Mlog(M)) 查询O(Mlog(N)+N)
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int N,M;const int SIZE = 50005;int c[SIZE];int A[SIZE];int Next[SIZE];int res[200005];int show[1000005];bool fir[SIZE];struct Q{ int l,r; int pos;}q[200005];int lowbit(int k){ return k&(-k);}void modify(int n,int v){ while(n <= N) { c[n] += v; n += lowbit(n); }}int sum(int n){ int ans = 0; while(n > 0) { ans += c[n]; n -= lowbit(n); } return ans;}int cmp(Q a, Q b){ return a.l < b.l;}int main(){ scanf("%d",&N); for(int i=1;i<=N;i++) scanf("%d",&A[i]); for(int i=N;i>=1;i--) { if(!show[A[i]]) { show[A[i]] = i; fir[i] = true; } else { Next[i] = show[A[i]]; fir[Next[i]] = false; fir[i] = true; show[A[i]] = i; } } scanf("%d",&M); for(int i=1;i<=M;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].pos = i; } sort(q+1,q+1+M,cmp); for(int i=1;i<=N;i++) if(fir[i]) { modify(i,1); } int qtemp = q[1].l; int ptr = 1; for(int i=1;i<=M;i++) { for(;ptr<q[i].l;ptr++) { if(fir[ptr]) { modify(ptr,-1); fir[ptr] = false; if(Next[ptr]) { fir[Next[ptr]] = true; modify(Next[ptr],1); } } } ptr = q[i].l; qtemp = q[i].l; res[q[i].pos] = sum(q[i].r) - sum(q[i].l-1); } for(int i=1;i<=M;i++) printf("%d\n",res[i]); return 0;}
0 0
- 查询区间内不同数字的个数 lydsy1878
- SPOJ DQUERY 区间内不同数的个数 主席树
- SPOJ DQUERY 区间内不同数的个数
- 区间内素数的个数
- 线段树离线处理(区间内不同的数的个数)hdu3333
- URAL 2080 Wallet 分块求无修改的区间内不同数的个数
- HDU 5327 区间里由不同的数字组成的数的个数-set-(枚举)
- SPOJ DQUERY 求区间内不同数的个数 主席树
- HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)
- [hdu5654 xiaoxin and his watermelon candy]区间内不同数的个数
- SPOJ DQUERY 求区间内不同数的个数 (主席树)
- SPOJ - DQUERY 主席树求区间中不同数字的个数
- HDU2089 一段区间内数字没有62和4的个数
- poj2528--Mayor's posters--离散化&查询区间的不同元素个数
- 区间内有多少个不同的数字(离线树状数组)
- HDU 5869 区间不同GCD的个数
- 求一段区间内素数的个数
- leetcode--求区间内的元素个数
- hdoj.5289 Assignment【单调队列】 2015/07/25
- IOS 图片虚化
- 关于cocos2dx如何通过jni进行c++与java的交互
- H3C MSR 20-10配置PPPOE
- Overlapped I/O with APCs
- 查询区间内不同数字的个数 lydsy1878
- cocos2dx Android签名总结
- 欧拉函数(模板)
- 开机自动开启小键盘灯
- 根据像素画圆
- css
- 新浪微博,腾讯微博mysql数据库主表猜想
- css的作业
- A计划(bfs)