BZOJ2038【莫队算法】

THE FIRST 莫队算法。

/**************************************************************
    Problem: 2038
    User: keyboarder_zsq
    Language: C++
    Result: Accepted
    Time:1644 ms
    Memory:2988 kb
****************************************************************/
 
//#include <bits/stdc++.h>
#include<cstdio>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N=5e4+10;
struct asd{
    LL a,b;
    int left,right;
    int id;
};
int n,m,col[N],pos[N];
asd q[N];
bool cmp(asd x,asd y)
{
    if(pos[x.left]==pos[y.left]) return x.right<y.right;
    return x.left<y.left;
}
bool cmp_id(asd x,asd y)
{
    return x.id<y.id;
}
 
LL ans,num[N];
void update(int p,int add)
{
    ans-=num[col[p]]*num[col[p]];
    num[col[p]]+=add;
    ans+=num[col[p]]*num[col[p]];
}
 
void solve()
{
    memset(num,0,sizeof(num));
    ans=0;
    for(int i=0,L=1,R=0;i<m;i++)
    {
        while(R<q[i].right)
        {
            update(R+1,1);
            R++;
        }
        while(R>q[i].right)
        {
            update(R,-1);
            R--;
        }
        while(L<q[i].left)
        {
            update(L,-1);
            L++;
        }
        while(L>q[i].left)
        {
            update(L-1,1);
            L--;
        }
        if(q[i].left==q[i].right)
        {
            q[i].a=0;q[i].b=1;
            continue;
        }
        q[i].a=ans-(q[i].right-q[i].left+1);
        q[i].b=(LL)(q[i].right-q[i].left+1)*(q[i].right-q[i].left);
        LL gcd=__gcd(q[i].a,q[i].b);
        q[i].a/=gcd;
        q[i].b/=gcd;
    }
}
 
int main()
{
    scanf("%d%d",&n,&m);
    int block=(int)sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&col[i]);
        pos[i]=(i-1)/block+1;
    }
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&q[i].left,&q[i].right);
        q[i].id=i;
    }
    sort(q,q+m,cmp);
    solve();
    sort(q,q+m,cmp_id);
    for(int i=0;i<m;i++)
        printf("%lld/%lld
",q[i].a,q[i].b);
    return 0;
}
/*
6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6
*/


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777418.html