最近,我学习Mo's algorithm查询的平方根分解,以加快某些问题的解决方案。
为了练习实现,我一直在尝试使用这个想法解决D. Powerful array(Codeforces的过去竞赛问题)。问题如下:
考虑任意子阵列。将定义为此子数组中整数的出现次数。子阵列的 power 被定义为所有整数的的总和(注意,只有正数的项不是零)。
它拥有:
使用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';
}
你能否提出任何非渐近(或甚至可能是渐近)的改进,可以加快程序的速度,足以超过时限?
我已经尝试过以下事情,但无济于事:
答案 0 :(得分:1)
你可以强度减少
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)
{
ans -= (2*cnt[arr[li]]-1)*arr[li];
cnt[arr[li]]--;
li++;
}
同样适用于其他人。
答案 1 :(得分:1)
您可以修改 MO的排序功能比较器功能cmp 。
您的版本:
exports.handler = async (event) => {
try {
const data = await httprequest();
//date to string
var d = Date();
var n = d.toString();
var iden = Date.now();
var identifier = iden.toString();
//add items to DynamoDB
console.log("LENGTH IS: " + data.response.docs.length);
for (var i = 0; i < data.response.docs.length; i++) {
var params = {
Item: {
date: identifier,
time: n,
id: data.response.docs[i].id,
journal: data.response.docs[i].journal
},
TableName: 'employee'
};
console.log(data.response.docs[i].id);
await docClient.put(params).promise();
}
console.log('Document inserted.');
return JSON.stringify(data);
} catch(err) {
console.log(err);
return err;
}
};
优化:
如果块是偶数,则可以按降序对R进行排序,如果块是奇数,则可以按升序对R进行排序。当从一个块移动到另一个块时,这将大大减少R指针的移动。
我的代码:
<input list="site" name="f" minlength="2" style="height:5.1em">
<datalist id="site" style="height:5.1em;overflow:hidden">