P4305 [JLOI2011]不重复数字
就离谱,4月10号可能是学离散化时交过,我都忘了
对于 100% 的数据,≤n≤5×104,给出的数在 32 位有符号整数范围内。。。
注意链式前向星的储存,data[cnt],head[M],for(int p=head[f(key)];p;p=data[p].next)
1.hash
1 //开散列哈希模板 2 #include<cstdio> 3 #include<string.h> 4 using namespace std; 5 const int maxn=5e4+10; 6 const int M=99997; //某一质数 7 int n,t; 8 int a[maxn]; 9 int head[M],cnt; 10 struct node{ 11 int val,key,next; 12 }data[maxn]; 13 int f(int key)//哈希函数 14 { 15 return key%M;//返回索引 16 } 17 int get(int key)//返回hash[key] 18 { 19 for(int p=head[f(key)];p;p=data[p].next) 20 if(data[p].key==key) return data[p].val; 21 } 22 bool modify(int key,int val)//是否存在键值对hash[key]=val 23 { 24 for(int p=head[f(key)];p;p=data[p].next) 25 if(data[p].key==key) return data[p].val==val; 26 return false; 27 } 28 void add(int key,int val) 29 { 30 if(modify(key,val)) return; 31 //if(get(key)==-1) return;//没有负数时也可用 32 data[++cnt]=(node){val,key,head[f(key)]}; 33 head[f(key)]=cnt; 34 }
2.离散化
思路是赋予每个值一个新的索引,具体是序列从小到大排序后这个数的位置。
同属于<algorithm>
unique()功能是将数组中相邻的重复元素去除。然而其本质是将重复的元素移动到数组的末尾,最后再将迭代器末尾指向第一个重复元素的下标。(不一定要求数组有序)
lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素
#include<cstdio> #include<algorithm> #include<string.h> using namespace std; const int maxn=5*1e4+10; int a[maxn]; int v[maxn]; int data[maxn],idx[maxn]; int main() { int T;scanf("%d",&T); while(T--) { memset(data,0,sizeof(data)); memset(idx,0,sizeof(idx)); memset(a,0,sizeof(a)); memset(v,0,sizeof(v)); int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); data[i]=a[i]; } sort(a,a+n); int len=unique(a,a+n)-a;//去重后的数组长度 for(int i=0;i<n;i++) idx[i]=lower_bound(a,a+len,data[i])-a;//得到data[i]在无重复升序排列a[i]中的位置,即原序列中为第几大的数 for(int i=0;i<n;i++) if(v[idx[i]]!=1) { printf("%d ",data[i]); v[idx[i]]=1; } putchar('\n'); } return 0; }
浙公网安备 33010602011771号