#分块#洛谷 3396 哈希冲突

本文介绍了一种使用分块技术优化处理大规模数据集的方法。通过预处理和合理的块大小设计,该算法能够在处理查询和更新操作时达到较好的时间复杂度。适用于需要频繁进行区间查询和单点修改的数据结构问题。

题目


分析

那么首先这道题可以用预处理,但是依然是 O ( n 2 ) O(n^2) O(n2),所以我们选择折中的分块,对于在范围内的修改的时候块内修改,输出 O ( 1 ) O(1) O(1),在超过的时候用暴力统计,时间复杂度 O ( n n ) O(n\sqrt n) O(nn )其中暴力询问和单点修改 O ( n ) O(\sqrt n) O(n ),但是这道题可以卡块的长度,所以自己算时间复杂度去吧


代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#define rr register
using namespace std;
int n,m,bk,a[150001],sum[61][61]; 
inline signed iut(){
    rr int ans=0,f=1; rr char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans*f;
}
inline void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
signed main(){
    n=iut(); m=iut(); bk=pow(1.0*n,1.0/3);
    for (rr int i=1;i<=n;++i){
    	a[i]=iut();
    	for (rr int j=1;j<=bk;++j)
    	    sum[j][i%j]+=a[i];
    }
    for (rr int i=1;i<=m;++i){
        rr char q=getchar();
        while (q!='A'&&q!='C') q=getchar();
        rr int x=iut(),y=iut();
        if (q=='C'){
        	for (rr int j=1;j<=bk;++j)
        	    sum[j][x%j]+=y-a[x];
        	a[x]=y;	    	
        }
        else if (x<bk) print(sum[x][y%x]),putchar(10);
        else{
            rr int ans=0;
            for (rr int i=y;i<=n;i+=x) ans+=a[i];
            print(ans); putchar(10);
        }
    }
    return 0;
}
### 洛谷哈希冲突解决方案 #### 预处理部分 为了高效解决洛谷P3396中的哈希冲突问题,可以采用分情况讨论的方式优化算法效率。当 $ p \leqslant \sqrt{n} $ 时,可以通过预处理来降低查询时间复杂度。具体来说,预先计算并存储所有满足条件的结果,使得后续查询操作可以在常数时间内完成[^1]。 以下是实现该逻辑的核心代码片段: ```cpp for (int j = 1; j * j <= n; j++) { dp[j][i % j] += a[i]; } ``` 这段代码通过遍历数组 `a` 并更新二维数组 `dp` 的方式完成了预处理工作。其中,`dp[p][r]` 表示模数为 `p` 且余数为 `r` 的所有位置上的数值之和[^2]。 --- #### 查询部分 对于 $ p > \sqrt{n} $ 的情况,则无法利用预处理数据结构快速响应请求。此时需采取暴力求解策略,即逐项累加符合条件的位置上的值。由于题目约束保证了此类情况下单次查询的时间开销不会超过 $ O(\sqrt{n}) $,因此整体性能仍然可接受[^1]。 下面是对应于较大质因数范围内的直接枚举方法: ```cpp if (x * x > n) { int sum = 0; for (int j = y; j <= n; j += x) { sum += a[j]; } printf("%d\n", sum); } ``` 此段程序实现了针对大素因子场景下的精确统计功能,并确保其运行成本维持在一个较低水平之上[^2]。 --- #### 修改操作支持 除了基本读取需求之外,还需要考虑动态调整输入序列的可能性。每当某个特定索引处发生改变之后,不仅需要同步修正原始列表本身的内容,而且还要重新评估那些依赖于此单元格的所有关联记录条目。幸运的是,在本题设定下执行这样的全局刷新动作最多只需花费线性级别的资源消耗即可达成目标[^1]。 下面展示了一种可行的更新机制实例化表达形式: ```cpp else { // Modify operation for (int j = 1; j * j <= n; j++) { dp[j][x % j] += y - a[x]; } a[x] = y; } ``` 这里的关键在于每次只涉及有限数量的相关子集成员受到影响,从而有效控制住了额外负担的程度[^2]。 --- ### 总结 综上所述,通过对不同规模参数分别设计专门化的应对措施,最终能够构建起一套兼顾速度与灵活性兼具的整体框架体系用于妥善处置各类可能出现的情形组合。这种方法既充分利用了先验知识简化常见模式识别过程,又保留足够的适应能力去面对罕见例外状况的发生可能性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值