莫隊算法(小Z的襪子,BZOJ 2038)

參考博客:

http://blog.csdn.net/xym_csdn/article/details/50889293


代碼

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 50010;

int N,M;
int c[maxn];
int n[maxn];
int b[maxn];

struct qr
{
    int l,r;
    int id;
    ll fz,fm;
    void print()
    {
        printf("%lld/%lld\n",fz,fm);
    }
}QR[maxn];

int cmp1(qr x,qr y)
{
    if(b[x.l]!=b[y.l]) return x.r<y.r;
    else return b[x.l]<b[y.l];
}

int cmp2(qr x,qr y)
{
    return x.id<y.id;
}

ll gcd(ll a,ll b)
{
    return !b?a:gcd(b,a%b);
}

void read()
{
    scanf("%d %d",&N,&M);
    b[0]=sqrt(N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",c+i);
        n[i]=0;
        b[i]=(i-1)/b[0]+1;
    }
    for(int i=1;i<=M;i++)
    {
        scanf("%d %d",&QR[i].l,&QR[i].r);
        QR[i].id=i;
    }
    sort(QR+1,QR+1+M,cmp1);
    int l=1,r=0;
    ll ans=0;
    for(int i=1;i<=M;i++)
    {
        QR[i].fm=1ll*(QR[i].r-QR[i].l+1)*(QR[i].r-QR[i].l);
        while(r<QR[i].r)
        {
            r++;
            ans=ans+(n[c[r]]<<1)+1;
            n[c[r]]++;
        }
        while(r>QR[i].r)
        {
            ans=ans-(n[c[r]]<<1)+1;
            n[c[r]]--;
            r--;
        }
        while(l<QR[i].l)
        {
            ans=ans-(n[c[l]]<<1)+1;
            n[c[l]]--;
            l++;
        }
        while(l>QR[i].l)
        {
            l--;
            ans=ans+(n[c[l]]<<1)+1;
            n[c[l]]++;
        }
        QR[i].fz=ans-(QR[i].r-QR[i].l+1);
        ll GCD = gcd(QR[i].fz,QR[i].fm);
        QR[i].fz/=GCD;
        QR[i].fm/=GCD;
    }
    sort(QR+1,QR+1+M,cmp2);
    for(int i=1;i<=M;i++)
        QR[i].print();
}

void solve()
{
    read();
}

int main()
{
    solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章