算法简介
莫队算法,是一种用于解决序列上的问题的离线算法,可以回答对于区间的询问,非常bug。
算法流程
先读入所有的询问,对询问的左端点分块。
在对询问排序,以左端点的块编号为第一关键字,以右端点为第二关键字。
然后遍历询问,同时维护L,R以及答案:对于当前区间,[l,r],不断移动左端点与右端点,直至l==L&&r==R。
算法复杂度
算法复杂度为 O(nn−√) ,可以用意识流跑一遍:
对于同一个块,R最多移动n次,然而,一共只有 n−√ 个块,所以复杂度就是 O(nn−√) 。
对于左端点,先讨论同一个块中的情况,每次移动至多为 n−√ ,于是总复杂度为 O(nn−√) ,对于不同块中的情况,只有 n−√ 个,即使每次 O(n) 也没关系。
综上,莫队算法的复杂度就是 O(nn−√) 。
入门题——小Z的袜子
题目链接
令 Ti 表示数i在 [L,R] 中出现的次数。
P=∑C2iC2R−L+1=∑Ti∗(Ti−1)/2(R−L+1)∗(R−L)/2=∑T2i−∑Ti(R−L+1)∗(R−L)
显然 ∑Ti =R-L+1,所以只要求 ∑T2i 就可以了。
这时我们惊奇的发现,似乎把刚学的莫队算法套上去就可以了!
用 cnti 表示元素i在当前区间中出现的次数。
每次添加一个元素,就往答案中加 (cnti+1)2−cnt2i ,再 cnti++ 这就是刚加入到元素的贡献。
每次删除一个元素,就减掉 cnt2i−(cnti−1)2 ,再 cnti−− 。
每次操作都是 O(1) 的,所以总复杂度是 O(nn−√) 。
/**************************************************************
Problem:
User: unicornt
Language: C++
Result: Accepted
Time: ms
Memory: kb
****************************************************************/
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int M=;
typedef long long ll;
struct Query{
int L,R,id;
}q[M];
int s,col[M];
ll ans[M][],cnt[M];
bool cmp(Query a,Query b){
if(a.L/s==b.L/s) return a.R<b.R;
return a.L/s<b.L/s;
}
int gcd(ll a,ll b){
return a?gcd(b%a,a):b;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
s=(int)sqrt(n);
for(int i=;i<=n;i++)
scanf("%d",&col[i]);
for(int i=;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
q[i]=(Query){a,b,i};
}
sort(q,q+m,cmp);
int L=,R=;
ll res=;
for(int i=;i<m;i++){
while(R<q[i].R){
R++;
res+=(cnt[col[R]]+)*(cnt[col[R]]+)-cnt[col[R]]*cnt[col[R]];
cnt[col[R]]++;
}
while(L<q[i].L){
res-=cnt[col[L]]*cnt[col[L]]-(cnt[col[L]]-)*(cnt[col[L]]-);
cnt[col[L]]--;
L++;
}
while(R>q[i].R){
res-=cnt[col[R]]*cnt[col[R]]-(cnt[col[R]]-)*(cnt[col[R]]-);
cnt[col[R]]--;
R--;
}
while(L>q[i].L){
L--;
res+=(cnt[col[L]]+)*(cnt[col[L]]+)-cnt[col[L]]*cnt[col[L]];
cnt[col[L]]++;
}
ans[q[i].id][]=res-R+L-;
ans[q[i].id][]=LL*(R-L+)*(R-L);
}
for(int i=;i<m;i++){
int G=gcd(ans[i][],ans[i][]);
ans[i][]/=G;
ans[i][]/=G;
if(!ans[i][]) ans[i][]=;
}
for(int i=;i<m;i++)
printf("%lld/%lld\n",ans[i][],ans[i][]);
return ;
}
一些题
codeforces 375D Tree and Queries 题解
codeforces 86D power array题解
hdu 4638 Group 题解