总觉得莫队算法是个很玄学的东东

就像是这个题,刚开始没有看题解,T了好几把,后来发现分块这种神奇的操作,后来,,,手贱用map,结果又T了。

改了以后特意试了一下,不用分块比用分块慢了十倍多

最后统计的时候注意排列组合的运用就🆗啦

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;

struct node
{
    int x,y,num;
    long long ans1,ans2;
}t[50100];

int n,m,l,r,qu;
int a[50100],ku[60000];
long long sum;
int q[50100];   

bool cmp(node k,node l)
{
    if(ku[k.x] == ku[l.x]) return k.y < l.y;  //分块
    else return k.x < l.x;
}

bool cmp1(node k,node l)
{
    return k.num < l.num;
}

long long gcd(long long x,long long y)
{
    if(y == 0) return x;
    return gcd(y, x % y);
}

int main()
{
    scanf("%d%d",&n,&m);
    qu = sqrt(n);
    for(int i = 1;i <= n; ++i)
        ku[i] = i / qu;
    for(int i = 1;i <= n; ++i)
    {
        scanf("%d",&a[i]);
    }
    for(int i = 0;i < m; ++i)
    {
        scanf("%d%d",&t[i].x,&t[i].y);
        t[i].num = i;
    }
    sort(t,t + m,cmp);
    l = 1; r = 0;
    sum = 0;
    for(int i = 0;i < m; ++i)
    {
        while(l < t[i].x)
        {
            sum -= q[a[l]] * (q[a[l]] - 1);
            q[a[l]]--;
            sum += q[a[l]] * (q[a[l]] - 1);
            l++;
        }
        while(l > t[i].x)
        {
            l--;
            sum -= q[a[l]] * (q[a[l]] - 1);
            q[a[l]]++;
            sum += q[a[l]] * (q[a[l]] - 1);
        }
        while(r > t[i].y)
        {
            sum -= q[a[r]] * (q[a[r]] - 1);
            q[a[r]]--;
            sum += q[a[r]] * (q[a[r]] - 1);
            r--;
        }
        while(r < t[i].y)
        {
            r++;
            sum -= q[a[r]] * (q[a[r]] - 1);
            q[a[r]]++;
            sum += q[a[r]] * (q[a[r]] - 1);
        }
        if(sum == 0 || l == r)
        {
            t[i].ans1 = 0;
            t[i].ans2 = 1;
        }
        else
        {
            long long W = 1LL* (r - l + 1) * (r - l);  //记得开long long 不然会乘爆
            long long x = gcd(sum,W);
            t[i].ans1 = sum / x;
            t[i].ans2 = W / x;
        }
    }
    sort(t,t + m,cmp1);
    for(int i = 0;i < m; ++i)
        printf("%lld/%lld\n",t[i].ans1,t[i].ans2);
    return 0;
}