洛谷P2709 小B的询问 基础莫队
洛谷P2709 小B的询问
标签
- 莫队
前言
- 死磕了一个多星期数论,把莫比乌斯反演,狄利克雷卷积,杜教筛,以及一些列和式的运算搞清楚了一些~由于洛谷的数论题都刷完了,所以先回到数据结构!初学莫队鸭
简明题意
- 求区间[L,R]中所有的数出现次数的平方和
思路
- 就是基础莫队的基础题了~下面是我的模板:
void add(int x)
{}
void remove(int x)
{}//这两个函数都是用来处理L,R指针移动时对答案的贡献,x是移走/来的点的id
for (int i = 1; i <= m; i++)
{
while (l < query[i].l) remove(l++);
while (l > query[i].l) add(--l);
while (r < query[i].r) add(++r);
while (r > query[i].r) remove(r--);
ans[query[i].id] = ans;
}
//下面是预处理
int len = sqrt(n);
...
query[i].k = (query[i].l - 1) / len + 1;//k是指块的id
//就这么些~很简单~
注意事项
- 一开始令l=1,r=0
总结
- 无
AC代码
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 50000 + 10;
struct Query
{
int l, r, id, k;
bool operator < (const Query& a)const
{
if (k == a.k) return r < a.r;
else return k < a.k;
}
};
int n, m, k, a[maxn];
Query query[maxn];
int ans0[maxn];
int ans, cnt[maxn];
void add(int x)
{
x = a[x];
ans += 2 * cnt[x] + 1;
cnt[x]++;
}
void remove(int x)
{
x = a[x];
ans -= 2 * cnt[x] - 1;
cnt[x]--;
}
void solve()
{
scanf("%d%d%d", &n, &m, &k);
int len = (int)sqrt(n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++)
scanf("%d%d", &query[i].l, &query[i].r), query[i].id = i, query[i].k = (query[i].l - 1) / len + 1;
sort(query + 1, query + 1 + m);
int l = 1, r = 0;
for (int i = 1; i <= m; i++)
{
while (l < query[i].l) remove(l++);
while (l > query[i].l) add(--l);
while (r < query[i].r) add(++r);
while (r > query[i].r) remove(r--);
ans0[query[i].id] = ans;
}
for (int i = 1; i <= m; i++)
printf("%d\n", ans0[i]);
}
int main()
{
solve();
return 0;
}
作者:danzh
QQ:1244536605
CSDN(和博客园同步):https://blog.csdn.net/weixin_42431507
-----------------------------------------------------------------------------------------------
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其
它人怎么样,我们也能够保持自己的本色走下去。
—clj