acwing17LSH

离散化

离散化就是一种映射,可以将大区间较分散的点,映射到小区间密集的点。或者说原数组中被赋值,被使用过的下标,映射到一个相对密集的下标区间。相对大小没有改变,却节省了储存空间。
如果数组数据范围<=1e5,可以用前缀和。
对a[x]+=c,用s[K]-s[L-1]来求前缀和。
如果数据范围很大,则需要用到离散化。
在这里插入图片描述
vector <整数> alls;的操作
unique(x,y)函数可以把一段数组的重复元素放到“后边”,并返回重复元素的起始下标。
在这里插入图片描述
find(x,y)函数可以去掉数组在x到y区间内的全部元素。
区间和
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
map<int,int>mp;//离散化 
int a[111111];
int main()

{
    
    
	int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		mp.clear(); //格式化,避免下一个测试数据出问题
		int n,q;
		scanf("%d%d",&n,&q);
		int count=0;//用来标记有几个不同的数的(不包括0),因为题意是问把某个数变成0,所以0不考虑 
		for(int i=1;i<=n;i++)
		{
    
    
			int num;
			scanf("%d",&num);
			a[i]=num;  
			if(num&&mp[num]==0) //如果这个数第一次出现,说明输入了一个新的数,所以conut+1 
			{
    
    
				count++;
			}
			mp[num]++;//用mp来储存该数出现的次数 
		}
		while(q--)
		{
    
    
			int x;
			scanf("%d",&x);
			if(x==1)    
			{
    
    
				int p,v;
				scanf("%d%d",&p,&v); //把第p个数,变成v 
				int y=a[p]; //先把第p个数记下来(这个数是还没改动之前的) ,记下来是为了下面,删掉时,这个数对应出现的次数-1 
				if(v&&mp[v]==0)  //如果新加的数,是之前没出现过的,就count+1,出现过的话,就没必要了 
				{
    
    
					count++;
				}
				mp[v]++;  //v这个数出现次数+1 
				a[p]=v;     //更新p位置的数为v 
				mp[y]--; //这是把之前那个旧的数,删掉, 
				if(y&&mp[y]==0) //如果旧的那个数完全没了,说明有个种类的数完全没了,conut-1 
				{
    
    
					count--;
				}
			}
			else 
			{
    
    
				printf("%d\n",count);  //count就是要输出的答案,即有几个不同的数(非零) 
			}
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_50909982/article/details/114990192
LSH
17