【发布时间】:2016-04-04 14:36:01
【问题描述】:
最近,我学习了Mo's algorithm 用于查询的平方根分解,以加快解决某些问题的速度。
为了练习实现,我一直在尝试使用这个想法解决D. Powerful array(过去在 Codeforces 上的竞赛问题)。问题如下:
考虑一个任意子数组。将 定义为该子数组中整数 的出现次数。子数组的幂定义为所有整数 的 之和(请注意,只有正数项不为零)。
它持有:
使用 Mo 的算法,我在 中编写了离线解决此问题的代码。我确信这个问题可以使用这个算法和时间复杂度来解决,因为我检查了其他人接受的代码,他们也使用了类似的算法。
不过,我的代码是gets a time limit exceeded verdict。
下面是我写的代码:
#include <ios>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <utility>
#include <map>
int sqt;
long long int ans = 0;
long long int arr[200005] = {};
long long int cnt[1000005] = {};
long long int tans[200005] = {};
struct el
{
int l, r, in;
};
bool cmp(const el &x, const el &y)
{
if (x.l/sqt != y.l/sqt)
return x.l/sqt < y.l/sqt;
return x.r < y.r;
}
el qr[200005];
int main()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
int n, q, a, b;
std::cin >> n >> q;
sqt = sqrt((double)(n))+27;
for (int i = 0; i < n; i++)
std::cin >> arr[i];
for (int i = 0; i < q; i++)
{
std::cin >> a >> b;
a--; b--;
qr[i].l = a;
qr[i].r = b;
qr[i].in = i;
}
std::sort(qr, qr+q, cmp);
int li = 0; //left iterator
int ri = 0; //right iterator
ans = arr[0];
cnt[arr[0]]++;
for (int i = 0; i < q; i++)
{
while (li < qr[i].l)
{
ans -= cnt[arr[li]]*cnt[arr[li]]*arr[li];
cnt[arr[li]]--;
ans += cnt[arr[li]]*cnt[arr[li]]*arr[li];
li++;
}
while (li > qr[i].l)
{
li--;
ans -= cnt[arr[li]]*cnt[arr[li]]*arr[li];
cnt[arr[li]]++;
ans += cnt[arr[li]]*cnt[arr[li]]*arr[li];
}
while (ri < qr[i].r)
{
ri++;
ans -= cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
cnt[arr[ri]]++;
ans += cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
}
while (ri > qr[i].r)
{
ans -= cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
cnt[arr[ri]]--;
ans += cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
ri--;
}
tans[qr[i].in] = ans;
}
for (int i = 0; i < q; i++)
std::cout << tans[i] << '\n';
}
您能否提出任何非渐近(甚至可能是渐近)改进,以使程序足够快以通过时间限制?
我已经尝试了以下方法,但无济于事:
我觉得我错过了一些重要的东西,因为我检查过的其他代码似乎以相当大的余地(大约半秒)通过了时间限制。然而,他们似乎使用与我的代码相同的算法。
任何帮助将不胜感激!
【问题讨论】:
-
您根据 a、l、r 和 s 定义子数组的幂,但是每个查询只指定了 a、l 和 r。总和是否超过所有 s?
-
是的,它是所有 s 的总和。我已将此添加到问题中,感谢您的澄清!
-
您提供的描述链接blog.anudeep2011.com/mos-algorithm 在底部说,“注意:该代码在提交时会给出 TLE,如果添加了快速 I/O,它将给出 AC。删除了快速 I/O 到保持代码干净。”似乎 IO 可能是问题所在,因为 cin/cout 不是很快。我建议检查 IO 时间与计算时间,看看 IO 是否可能是超出时间限制的原因。
标签: c++ algorithm data-structures