1. 程式人生 > 實用技巧 >根號分治刷題記錄

根號分治刷題記錄

根號分治就是,如果m次詢問,每次詢問規模都是<=n;然後就分出大於\(\sqrt(n)\)的部分和小於\(\sqrt(n)\)的部分,其中小於\(\sqrt(n)\)的部分往往可以O(n)預處理,大於\(\sqrt(n)\)的部分暴力計算每次只需要花費O(\(\sqrt(n)\)),總之就是暴力美學啦。。。。

洛谷P3396雜湊衝突

注意到\(p<\sqrt(n)\)的部分可以預處理,然後修改也可以O(\(\sqrt(n)\))修改,於是。。。

#include <bits/stdc++.h>
#define N 150010
#define SN 400
#define f(c,a,b) for(int c=a; c<=b; c++)

using namespace std;
int v[N];
int n, m, c;
int a[SN][SN];

void pre(){ f(i,1,c) f(j,1,n) a[i][j%i] += v[j]; }
void change(int p, int x){ f(i,1,c) a[i][p%i] += x; }

int main(){
    //freopen("owo.in","r",stdin);
    cin >> n >> m;
    c = (int)sqrt(n);
    f(i,1,n) scanf("%d", &v[i]);
    pre();
    int x, y;
    char pd[10];
    f(i,1,m){
        scanf("%s%d%d", &pd, &x, &y);
        if(pd[0] == 'A'){  //ask
            int ans = 0;
            if(x >= c) for (int j=y; j<=n; j+=x) ans += v[j];
            else ans = a[x][y];
            printf("%d\n", ans);
        }else{ //change
            change(x, y-v[x]);
            v[x] = y;
        }
    }
    return 0;
}