zoukankan      html  css  js  c++  java
  • 求区间内不同数字的个数(树状数组)

    题干

    给一个序列,让你求[l, r]中不同数字的个数

    输入

    输入一个n,随后是含有n个数字的序列

    输入一个q,随后是两个整数,代表查询区间

    输出

    q个查询的结果

    样例

    Input
    5
    1 1 2 1 3
    3
    1 5
    2 4
    3 5
    
    Output
    3
    2
    3 
    

    思路

    用一个树状数组记录序列前i个数字中,不同数字的个数。

    从一个查询区间的左侧开始扫描:

    1. 数字首次出现时,当前位置加一,且用map记录下当前数字出现的位置
    2. 数字非首次出现时,当前位置加一,但是上次出现的位置要减一
    

    一个查询区间结束后,getsum(r) - getsum(l - 1)即为答案。

    仔细思考上述过程,当执行第二种情况时,会破坏之前的结果,因此整个序列扫描的过程,必须保证一次完成。

    因此要注意:

    1. 按照查询区间的右端点值进行排序(当前的会破坏前面的结果)
    2. 保证整个序列中的元素仅扫描一次,即代码中的`pre = query[i].r + 1;`而不是`pre = query[i + 1].l;`
    

    代码

    #include <stdio.h>
    #include <string>
    #include <stdlib.h>
    #include <iostream>
    #include <vector>
    #include <string.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    const int maxn = 10000;
    int n = 0, q = 0;
    
    struct Query{
    	int id, l, r;
    	bool operator< (Query a) const{
    		return r < a.r;
    	}
    }query[maxn];
    
    
    
    int v[maxn], sum[maxn], ans[maxn];
    
    int lowbit(int x){
    	return x & (-x);
    }
    
    void change(int i, int a){
    	while(i <= n){
    		sum[i] += a;
    		i += lowbit(i);
    	}
    }
    
    int getsum(int i){
    	int sum_t = 0;
    	while(i > 0){
    		sum_t += sum[i];
    		i -= lowbit(i);
    	}
    	return sum_t;
    }
    
    int main() {
    	
    	while(~scanf("%d", &n)){
    		memset(v, 0, sizeof(v));
    		memset(sum, 0, sizeof(sum));
    		memset(ans, 0, sizeof(ans));
    		
    		int t = 0;
    		for(int i = 1; i <= n; i++){
    			scanf("%d", &v[i]);
    		}
    		scanf("%d", &q);
    		for(int i = 1; i <= q; i++){
    			scanf("%d%d", &query[i].l, &query[i].r);
    			query[i].id = i;
    		}
    		sort(query + 1, query + q + 1);
    		
    		int pre = 1;
    		map<int, int> mymap;
    		for(int i = 1; i <= q; i++){
    			for(int j = pre; j <= query[i].r; j++){
    				//已存在 
    				if(mymap[v[j]]){
    					change(mymap[v[j]], -1);
    				}
    				mymap[v[j]] = j;
    				change(j, 1);
    			}
    			pre = query[i].r + 1;
    			ans[query[i].id] = getsum(query[i].r) - getsum(query[i].l - 1);
    		}
    		
    		for(int i = 1; i <= q; i++){
    			cout << ans[i] << endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    查看 FormData 中已存在的值
    dedecms 后台可以上传mp4,但无法选择
    dedecms 文章根据 权重排序
    js 单行注释
    dedecms给图片加水印覆盖整张图片
    Nginx服务器 配置 https
    dedecms 后台 菜单点击后打开的慢
    用 PHP文件引入css样式
    TFT、LCD、OLED、LPTS、CRT等显示屏的区别
    ORCAD中的一些操作小技巧
  • 原文地址:https://www.cnblogs.com/woxiaosade/p/12305677.html
Copyright © 2011-2022 走看看