• 洛谷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;
    }
    代码
  • 相关阅读:
    Angularjs总结(一)表单验证
    list集合中指定字段去重
    NodeJS学习笔记—2.AMD规范
    NodeJS学习笔记—1.CommonJS规范
    WCF上传、下载、删除文件
    .net RAW(16)与GUID互相转换
    Angularjs总结(六) 上传附件
    可以打开mdb文件的小软件
    数据库导出导入操作(expdp,impdp)
    用Ueditor存入数据库带HTML标签的文本,从数据库取出来后,anjular用ng-bind-html处理带HTML标签的文本
  • 原文地址:https://www.cnblogs.com/halifuda/p/8626026.html
Copyright © 2020-2023  润新知