zoukankan      html  css  js  c++  java
  • 洛谷P3396哈希冲突

    题意:
    给出长度为n的序列A1、A2、A3……An,进行M次操作:‘A’操作输入x、y,求序列中下标i%x==y的所有数的和;‘C’操作输入x、y,将Ax的值改为y。

    题解:

    题解真的非常神奇……思路是这样的:

    首先暴力的想法:

    for(int i=y;i<=n;i+=x) ans+=A[i];
    纯暴力

    这样是O(n^2)的。之后有O(1)求答案的预处理,预处理出每个数在下标%p时对答案的贡献:

    void Init(){
        for(int i=1;i<=n;i++){
            for(int p=1;p<n;p++){
                ans[p][i%p]+=a[i];
            }
        }
        return;
    }
    预处理

    然而,这个预处理的时间和空间复杂度都达到了O(n^2)……不过我们可以利用根号来进行优化:

    void Init(){
        int size=sqrt(n);
        for(int i=1;i<=n;i++){
            for(int p=1;p<=size;p++){
                ans[p][i%p]+=a[i];
            }
        }
        return;
    }
    根号预处理

    这样时间和空间的复杂度降到了O(n*sqrt(n))。

    预处理后,对于询问中模数小于等于sqrt(n)的,我们都可以O(1)解决;而对于我们没有处理出的,即模数大于sqrt(n)的,我们知道序列里对答案有贡献的数不会超过sqrt(n)个,所以暴力求和,时间复杂度维持在O(sqrt(n))以下。

    对于修改,暴力更新预处理的结果即可,复杂度维持在O(sqrt(n))以下。

    所以总复杂度为O(n*sqrt(n))。

    只能说根号还是很神奇的……

    代码:

    #include<cstdio>
    #include<cmath>
    #define MXN 150000+1
    #define MXM 150000+1
    int n,m;
    int a[MXN],ans[400][400];
    char cmd[2];
    int x,y,size;
    void Init(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        size=sqrt(n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=size;j++){
                ans[j][i%j]+=a[i];
            }
        }
        return;
    }
    void Query(){
        scanf("%d%d",&x,&y);
        if(x<=size) printf("%d
    ",ans[x][y]);
        else{
            int sum=0;
            for(int i=y;i<=n;i+=x) sum+=a[i];
            printf("%d
    ",sum);
        }
        return;
    }
    void Change(){
        scanf("%d%d",&x,&y);
        for(int i=1;i<=size;i++){
            ans[i][x%i]=ans[i][x%i]-a[x]+y;
        }
        a[x]=y;
        return;
    }
    int main(){
        Init();
        while(m--){
            scanf("%s",cmd);
            if(cmd[0]=='A') Query();
            if(cmd[0]=='C') Change();
        }
        return 0;
    }
    代码
  • 相关阅读:
    Redis流程初始认知
    浅谈windows和linux进程和线程的区别
    linux下的信号量PV操作进阶之路
    linux下线程以及pthread库
    分清问题的主次
    linux下主线程return 0和pthread_exit(NULL)的区别
    进程和线程的区别
    注意搜索的陷阱
    模拟主线程等待子线程的过程
    【伯乐在线】编程面试的10大算法概念汇总
  • 原文地址:https://www.cnblogs.com/halifuda/p/8626026.html
Copyright © 2011-2022 走看看