P1494 [国家集训队]小Z的袜子(莫队算法)
莫队板子
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
struct Query{
int l,r,aid;
}query[55000];
int ansa[55000],ansb[55000],c[55000],blocknum,midans,sz,belong[55000],n,m,a[55000],lx,rx;
bool cmp(Query a,Query b){
return belong[a.l]==belong[b.l]?a.r<b.r:a.l<b.l;
}
int gcd(int a,int b){
return (b==0)?a:gcd(b,a%b);
}
void move(int pos,int cs){
midans-=c[a[pos]]*(c[a[pos]]);
c[a[pos]]+=cs;
midans+=c[a[pos]]*(c[a[pos]]);
}
signed main(){
scanf("%lld %lld",&n,&m);
sz=sqrt(n);
blocknum=n/sz;
if(n%sz)
blocknum++;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
belong[i]=(i-1)/sz+1;
}
for(int i=1;i<=m;i++)
scanf("%lld %lld",&query[i].l,&query[i].r),query[i].aid=i;
sort(query+1,query+m+1,cmp);
lx=1,rx=0;
for(int i=1;i<=m;i++){
while(lx<query[i].l)
move(lx,-1),lx++;
while(lx>query[i].l)
move(lx-1,1),lx--;
while(rx<query[i].r)
move(rx+1,1),rx++;
while(rx>query[i].r)
move(rx,-1),rx--;
//move
if(query[i].l==query[i].r){
ansa[query[i].aid]=0,ansb[query[i].aid]=1;
continue;
}
ansa[query[i].aid]=midans-(query[i].r-query[i].l+1);
ansb[query[i].aid]=(query[i].r-query[i].l+1)*(query[i].r-query[i].l);
int Gcd=gcd(ansa[query[i].aid],ansb[query[i].aid]);
ansa[query[i].aid]/=Gcd;
ansb[query[i].aid]/=Gcd;
}
for(int i=1;i<=m;i++)
printf("%lld/%lld\n",ansa[i],ansb[i]);
return 0;
}