小Z的袜子(hose) HYSBZ - 2038 莫队+分块

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pll;
const int maxn=5e5+10;
int n,m;
int block;
int a[maxn],belong[maxn];
pll ans[maxn];
ll sum;
ll num[maxn];
struct node{
    int l,r;
    int id;
}q[maxn];
bool cmp(node a,node b)
{
    //先所在块 
    if(belong[a.l]==belong[b.l])
        return a.r<b.r;
    //按所在快排序 
    return belong[a.l]<belong[b.l];
}
void add(int x)
{
    sum-=num[a[x]]*num[a[x]];
    num[a[x]]++;
    sum+=num[a[x]]*num[a[x]];
}
void del(int x)
{
    sum-=num[a[x]]*num[a[x]];
    num[a[x]]--;
    sum+=num[a[x]]*num[a[x]];
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    int sz=sqrt(n);
    for(int i=1;i<=n;i++)
        belong[i]=i/sz;
    for(int i=1;i<=m;i++)
    {
        cin>>q[i].l>>q[i].r;
        q[i].id=i;
    }
    sort(q+1,q+1+m,cmp);
    int l=1,r=0;
    sum=0;
    for(int i=1;i<=m;i++)
    {
        int id=q[i].id;
        while(r<q[i].r)
        {
            r++;
            add(r);
        }
        while(r>q[i].r)
        {
            del(r);
            r--;
        }
        while(l>q[i].l)
        {
            l--;
            add(l);
        }
        while(l<q[i].l)
        {
            del(l);
            l++;
        }
        //减去重复拿相同的 
        ans[id].first=sum-(q[i].r-q[i].l+1);
        //所有方案 
        ans[id].second=(ll)(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
        if(ans[id].first==0)
        {
            ans[id].second=1;
            continue;
        } 
        ll tmp=__gcd(ans[id].first,ans[id].second);
        ans[id].first=ans[id].first/tmp;
        ans[id].second=ans[id].second/tmp;
    }
    for(int i=1;i<=m;i++)
        cout<<ans[i].first<<"/"<<ans[i].second<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12349500.html