题解
2024-12-10 20:41:46
发布于:广东
54阅读
0回复
0点赞
提示:想办法把每次询问的运行次数控制在 以内
注意到 ,明显就是给暴力分块做的
对于这类问题,一次查询运算次数只需要不超过 次就行,这里我取 的近似值 .
当 时,运算次数必定小于 ,直接暴力枚举.
所以我们只需要思考 的情况就行.
340pts
按内存极限预处理 的情况,剩下的暴力.
为当 时的答案.
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
int a[300005], dabiao[25][300005];
signed main(){
cin.tie(nullptr) -> sync_with_stdio(0);
cout.tie(nullptr) -> sync_with_stdio(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i < 24; i++){
for(int j = n; j; j--){
dabiao[i][j] = dabiao[i][j + i] + a[j];//处理后缀和
}
}
int m;
cin >> m;
while(m--){
int l, len;
cin >> l >> len;
if(len < 24) cout << dabiao[len][l] << '\n';//直接输出
else{
int ct = 0;
for(int i = l; i <= n; i += len) ct += a[i];
cout << ct << '\n';
}
}
return 0;
}
500pts
仔细思考,如果我们隔一个预处理一个,如
1 2 3 4 5 6 7
变成
1 3 5 7
2,4,6查询时再计算,那这样运算次数只多了一次,但是内存却省了一半!
按照这个办法,把 的步长改为 ,运行次数仍然不超过 .
#include <iostream>
#include <cstdio>
#include <vector>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#define int long long
#define N 600
//块长:600
using namespace std;
int a[600005];
vector <vector <int>> dp[605], dp2[605];//dp2指向的真实的数,为方便预处理增加了一维
signed main(){
cin.tie(nullptr) -> sync_with_stdio(0);
cout.tie(nullptr) -> sync_with_stdio(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= 600; i++){
dp[i].resize(i, vector <int>(n / i / N + 5));
dp2[i].resize(i, vector <int>(n / i / N + 5));
for(int j = 0; j < i; j++){
int tmp = n / N / i * N * i + j;
dp2[i][j][n / N / i + 1] = tmp + i * N;
for(int k = n / N / i; k >= 0; k--, tmp -= i * N){
dp[i][j][k] = dp[i][j][k + 1];
for(int l = 0; l < N * i; l += i){
dp[i][j][k] += a[tmp + l];//计算后缀和
}
dp2[i][j][k] = tmp;
}
}
}
int m;
cin >> m;
while(m--){
int idx, len;
cin >> idx >> len;
if(len * len > n){
int ans = 0;
for(int i = idx; i <= n; i += len){//暴力
ans += a[i];
}
cout << ans << '\n';
continue;
}
int ans = dp[len][idx % len][idx / len / N + 1];
for(int i = idx; i < dp2[len][idx % len][idx / len / N + 1]; i += len){//处理前面没加到的数
ans += a[i];
}
cout << ans << '\n';
}
return 0;
}
拓展:预处理现在进行了 次运算,但事实上可以降至 次运算,因为我懒留给你们思考的空间,代码就不放了.
这里空空如也
有帮助,赞一个