小Z的袜子(hose) HYSBZ - 2038 [莫队算法]

小Z的袜子(hose) HYSBZ - 2038 

题意不说了,作为入门题/模板,在代码里解释一些细节问题

关于复杂度是O(n*sqrt(n)).其中,n和m为同一数量级. 证明自行百度

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll c[N],num[N],p[N];
struct node{
    ll l,r,id,fz,fm;
}q[N];

ll ans;

bool cmp1(node a,node b){
    if(p[a.l]==p[b.l])  return a.r<b.r;
    else    return a.l<b.l;
}

bool cmp2(node a,node b){
    return a.id < b.id;
}

void update(int pos,int flag){
    ans-=num[c[pos]]*num[c[pos]];
    num[c[pos]]+=flag;
    ans+=num[c[pos]]*num[c[pos]];
    return ;
}

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    ll n,m;
    cin >>n>>m;
    for(int i=1;i<=n;i++)   cin >>c[i];
    int t=sqrt(n);///分块的长度
    for(int i=1;i<=n;i++)   p[i]=(i-1)/t+1;
    for(int i=1;i<=m;i++)  cin >> q[i].l>>q[i].r,q[i].id=i;///给每个询问放入结构体
    sort(q+1,q+1+m,cmp1);///根据莫队的算法来排序
    ll l=1,r=0;///一开始是一个空区间,ans=0
    for(int i=1;i<=m;i++){
        ///注意下更新的是哪一个点
        while(r<q[i].r) update(r+1,1),r++;
        while(r>q[i].r) update(r,-1),r--;
        while(l<q[i].l) update(l,-1),l++;
        while(l>q[i].l) update(l-1,1),l--;
    
        q[i].fz=ans-(q[i].r-q[i].l+1);
        q[i].fm=(q[i].r-q[i].l)*(q[i].r-q[i].l+1);
        ll GCD=__gcd(q[i].fz,q[i].fm);
        q[i].fz/=GCD;
        q[i].fm/=GCD;
    }
    ///排序按照id
    sort(q+1,q+1+m,cmp2);
    for(int i=1;i<=m;i++)
        cout << q[i].fz <<"/"<<q[i].fm <<"\n";
    return 0;
}


猜你喜欢

转载自blog.csdn.net/haipai1998/article/details/80705606