[bzoj 2038]莫队算法

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

long long gcd(long long a,long long b)
{
    return a==0?b:gcd(b%a,a);
}

const int maxn=50005;
int block_size;

struct Query
{
    int l,r;
    int id;
    long long ans,L;
    bool operator<(const Query &q) const
    {
        return (l/block_size<q.l/block_size) || ((l/block_size==q.l/block_size)&&(r<q.r));
    }
}query[maxn];
int a[maxn];
long long cnt[maxn];
pair<long long,long long> ans[maxn];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    block_size=(int)sqrt(n);
    for (int i=0;i<n;i++) scanf("%d",&a[i]);
    for (int i=0;i<m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x--;
        y--;
        query[i].id=i;
        query[i].l=x;
        query[i].r=y;
        query[i].ans=0;
        query[i].L=y-x+1;
    }
    sort(query,query+m);
//    for (int i=0;i<m;i++) printf("%d %d
",query[i].l,query[i].r);
    if (m>0)
    {
        for (int i=query[0].l;i<=query[0].r;i++)
        {
            cnt[a[i]]++;
        }
        for (int i=0;i<maxn;i++)
        {
            query[0].ans+=(cnt[i]-1)*cnt[i]/2;
        }
    }
    for (int i=1;i<m;i++)
    {
        query[i].ans=query[i-1].ans;
        while (query[i-1].r<query[i].r)
        {
            query[i-1].r++;
            int j=a[query[i-1].r];
            query[i].ans+=cnt[j];
            cnt[j]++;
        }
        while (query[i-1].l>query[i].l)
        {
            query[i-1].l--;
            int j=a[query[i-1].l];
            query[i].ans+=cnt[j];
            cnt[j]++;
        }
        while (query[i-1].r>query[i].r)
        {
            query[i-1].r--;
            int j=a[query[i-1].r+1];
            cnt[j]--;
            query[i].ans-=cnt[j];
        }
        while (query[i-1].l<query[i].l)
        {
            query[i-1].l++;
            int j=a[query[i-1].l-1];
            cnt[j]--;
            query[i].ans-=cnt[j];
        }
    }
    for (int i=0;i<m;i++)
    {
        long long fi=query[i].ans;
        long long se=query[i].L*(query[i].L-1)/2;
        if (fi==0) se=1;
        long long g=gcd(fi,se);
        ans[query[i].id]=make_pair(fi/g,se/g);
    }
    for (int i=0;i<m;i++)
    {
        printf("%lld/%lld
",ans[i].first,ans[i].second);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/acmsong/p/7374338.html