哈希冲突[分块(思想)]

题目背景

此题约为NOIP提高组Day2T2难度。

题目描述

众所周知,模数的hash会产生冲突。例如,如果模的数p=7,那么411便冲突了。

B君对hash冲突很感兴趣。他会给出一个正整数序列value[]

自然,B君会把这些数据存进hash池。第value[k]会被存进(k%p)这个池。这样就能造成很多冲突。

B君会给定许多个px,询问在模p时,x这个池内数的总和

另外,B君会随时更改value[k]。每次更改立即生效。

保证1<=p<n1<=p<n1<=p<n .

输入输出格式

输入格式:

第一行,两个正整数n,m,其中n代表序列长度,m代表B君的操作次数。

第一行,n个正整数,代表初始序列。

接下来m行,首先是一个字符cmd,然后是两个整数x,y

  • cmd=‘A‘,则询问在模x时,y池内数的总和
  • cmd=‘C‘,则将value[x]修改为y

输出格式:

对于每个询问输出一个正整数,进行回答。

输入输出样例

输入样例#1:

10 5
1 2 3 4 5 6 7 8 9 10
A 2 1
C 1 20
A 3 1
C 5 1
A 5 0

输出样例#1:

25
41
11

说明

样例解释

A 2 1的答案是1+3+5+7+9=25.

A 3 1的答案是20+4+7+10=41.

A 5 0的答案是1+10=11.

数据规模

对于10%的数据,有n<=1000,m<=1000.

对于60%的数据,有n<=100000.m<=100000.

对于100%的数据,有n<=150000,m<=150000.

保证所有数据合法,且1<=value[i]<=1000.

题解

做法分析:

  (sqrt(),不只是分块)

  (1)首先,我们先处理出sqrt()内的模数池的值,这样询问就只要o(1),预处理o(n√n)。

  (2)其次,当模数大于sqrt()时,我们暴力一次的代价为o(√n)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int ans[400][150001],ch[150001],n,m,tmp;
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)w=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar();
    return x*w;
}

void build()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=tmp;j++)
        ans[j][i%j]+=ch[i];
}

void change(int x,int v)
{
    for(int i=1;i<=tmp;i++)
    ans[i][x%i]=ans[i][x%i]-ch[x]+v;
    ch[x]=v;
}

int query(int x,int v)
{
    int ans=0;
    for(int i=v;i<=n;i+=x)
    {
        ans+=ch[i];
    }
    return ans;
}

int main()
{
    n=read();m=read();
    tmp=sqrt(n);
    for(int i=1;i<=n;i++)ch[i]=read();
    build();
    for(int i=1;i<=m;i++)
    {
        char qwq;cin>>qwq;int x=read();int y=read();
        if(qwq==‘A‘){if(x<=tmp)printf("%d\n",ans[x][y]);
        else printf("%d\n",query(x,y));}
        if(qwq==‘C‘)change(x,y);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hhh1109/p/8597720.html

时间: 2024-10-10 00:50:23

哈希冲突[分块(思想)]的相关文章

luogu P3396 哈希冲突(分块?)

我们可以维护一个\(f[i][j]\)代表%\(i\)意义下得\(j\)的答案.然后维护就炸了. 先设\(x=\sqrt{n}\)然后我们发现,当\(i>x\)时我们直接暴力复杂度为\(O(x)\),然后我们对\(i\leq{x}\)的i维护\(f[i][j]\),这样询问复杂度\(O(1)\),维护复杂度\(O(x)\).就可以通过此题了. #include<iostream> #include<cstring> #include<cstdio> #includ

处理哈希冲突的线性探测法

哈希表,是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表.(摘自维基百科) 对不同的关键字可能得到同一散列地址,即k1!=k2,而f(k1)=f(k2),这种现象称为碰撞(英语:Collision),也叫哈希冲突. 处理哈希冲突的方法有很多种: 闭散列法 开链法(哈希桶) 素数表 字符串哈希算法 在这里我们讨论最简单的闭散

算法6-3:解决哈希冲突之线性探针

线性探针是另外一种解决哈希冲突的办法.这种办法的基本思想就是当遇到哈希冲突时,寻找下一个空位,直到找到空位为止. 示例 先插入一个值S,如下图. 插入其他的一些值,这些值的哈系没有冲突,得到下图的结果. 再插入一个值H,由于H与A的哈系冲突,因此需要寻找一个空的位置. 找到了空位 插入 代码 public class LinearProbeST<Key, Value> { private static final int M = 100; private Key[] keys = (Key[]

一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部结构 Linux 查询含有某字符串内容的命令grep 查询进程.GC状态.杀死进程 Hadoop五种节点介绍 -----------------------------------------------------------------------------------------------

【数据结构】处理哈希冲突的开链法(哈希桶)算法实现

实现哈希表时,我们常见的方法是线性探测.二次探测,这两个算法也很简单.若有兴趣,可以查看我的博客.但是,这两个算法有一个共同点就是:空间利用率低.为什么这么说呢?线性探测.二次探测的高效性很大程度上要取决于它的载荷因子,载荷因子即:存放关键字个数/空间大小. 通过查阅资料,我发现,使用素数做除数可以减少哈希冲突(具体原因不详,大师专研的,发现很好用,就在这里分享给大家).见下: ----素数表 // 使用素数表对齐做哈希表的容量,降低哈希冲突 const int _PrimeSize = 28;

哈希冲突的处理【闭散列方法-线性探测和二次探测】

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 给定表M,存在函数Hash(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数Hash(key)为哈希(Hash) 函数. 构造哈希表的两种方法 1.直接定址法--取关键字的某个线性函数为散列地

算法学习 - HashTable开放地址法解决哈希冲突

开放地址法解决哈希冲突 线性开放地址法 线性开放地址法就是在hash之后,当发现在位置上已经存在了一个变量之后,放到它下一个位置,假如下一个位置也冲突,则继续向下,依次类推,直到找到没有变量的位置,放进去. 平方开放地址法 平方地址法就是在hash之后,当正确位置上存在冲突,不放到挨着的下一个位置,而是放到第2^0位置,假如继续冲突放到2^1的位置,依次2^3... 直到遇到不冲突的位置放进去. 双散列开放地址法 双散列同上,不过不是放到2^的位置,而是放到key - hash(key, tab

算法学习 - Hash Table操作,分离链接法解决哈希冲突

分离链接法 hash table是映射机制的,最大的优点就是它的操作是O(1)级别的.但是会出现哈希冲突,这就需要几种办法来解决.这里先说一种:分离链接法. 就是当插入的位置已经存在一个值之后,那么在这个值之后插入,就可以了,也叫拉链法.(但是其实会降低查找速度,变成O(n)级别) 下面是代码: // // main.cpp // HashTable_SeparateChaining // // Created by Alps on 14-8-5. // Copyright (c) 2014年

【干货】C++哈希桶(开链法解决哈希冲突)类的实现

开链法(哈希桶)是解决哈希冲突的常用手法,结构如下: 数据结构的设计思路是这样的,定义一个K-V的链式节点(Node),以数组方式存储节点指针 实现代码如下: #include<vector> #include"HashTable.h" size_t GetSize() { static size_t index = 0; const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize]