国家集训队 小Z的袜子
自从“HH的项链”被树状数组干爆了之后,莫队终于扬眉吐气了一把。
很经典的莫队模板题,好像没什么好说的……
代码有(十)些(分)冗长,将就着看吧……
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
struct zzz{
LL l,r,pos;
}que[50010]; int n,m,sq;
bool cmp(zzz x,zzz y){
if(x.l/sq != y.l/sq) return x.l/sq < y.l/sq;
else return x.r < y.r;
}
LL read(){
LL k=0; char c=getchar();
for(;c<'0'||c>'9';) c=getchar();
for(;c>='0'&&c<='9';c=getchar())
k=(k<<3)+(k<<1)+c-48;
return k;
}
LL a[50010],tong[50010];
struct hhh{
LL fm,fz;
}anss[50010];
LL gcd(LL x,LL y){
return x%y==0? y:gcd(y,x%y);
}
int main(){
n=read(),m=read(); sq=sqrt(n);
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++)
que[i].l=read(),que[i].r=read(), que[i].pos=i;
sort(que+1,que+m+1,cmp);
LL l=1,r=0,ans=0;
for(int i=1;i<=m;i++){
while(l<que[i].l){
if(tong[a[l]]>0)
ans-=tong[a[l]]*tong[a[l]];
tong[a[l++]]--;
if(tong[a[l-1]]>0)
ans+=tong[a[l-1]]*tong[a[l-1]];
}
while(l>que[i].l){
if(tong[a[l-1]]>0)
ans-=tong[a[l-1]]*tong[a[l-1]];
tong[a[--l]]++;
if(tong[a[l]]>0)
ans+=tong[a[l]]*tong[a[l]];
}
while(r<que[i].r){
if(tong[a[r+1]]>0)
ans-=tong[a[r+1]]*tong[a[r+1]];
tong[a[++r]]++;
if(tong[a[r]]>0)
ans+=tong[a[r]]*tong[a[r]];
}
while(r>que[i].r){
if(tong[a[r]]>0)
ans-=tong[a[r]]*tong[a[r]];
tong[a[r--]]--;
if(tong[a[r-1]]>0)
ans+=tong[a[r+1]]*tong[a[r+1]];
}
if(l==r||ans==r-l+1){
anss[que[i].pos].fz=0; anss[que[i].pos].fm=1;
continue;
}
LL g=gcd(ans-(r-l+1),(r-l+1)*(r-l));
anss[que[i].pos].fz=(ans-(r-l+1))/g;
anss[que[i].pos].fm=((r-l+1)*(r-l))/g;
}
for(int i=1;i<=m;i++)
printf("%lld/%lld\n",anss[i].fz,anss[i].fm);
return 0;
}