P1494 [国家集训队]小Z的袜子 题解

莫队算法,进行组合数转换,就能发现贡献度只要维护平方和就行

网上有很多好题解,我只是记录一下我的代码

注意本题两个int数相乘会爆int,所以要养成开long long的好习惯,不然螺旋升天

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5;
ll ans1[N];
ll ans2[N];
int n,m;
ll cnt[N];
ll a[N];
ll res;
ll pos[N];
struct node{
    ll l,r;
    ll k;
}q[N];
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
bool cmp(node a,node b){
    if(pos[a.l]==pos[b.l])
    return a.r<b.r;
    return pos[a.l]<pos[b.l];
}
void add(int x){
    res+=2*cnt[a[x]];
    res++;
    cnt[a[x]]++;
    
}
void sub(int x){
    res-=2*cnt[a[x]];
    res++;
    cnt[a[x]]--;
}
int main(){
    int i;
    cin>>n>>m;
    int block=sqrt(n);
    for(i=1;i<=n;i++){
        cin>>a[i];
        pos[i]=(i-1)/block+1;
    }
    for(i=1;i<=m;i++){
        cin>>q[i].l>>q[i].r;
        q[i].k=i;
    }
    sort(q+1,q+1+m,cmp);
    ll l=q[1].l;
    ll r=q[1].r;
    for(i=q[1].l;i<=q[1].r;i++){
       add(i);     
    }
    ans1[q[1].k]=res-(q[1].r-q[1].l+1);
    ans2[q[1].k]=(q[1].r-q[1].l+1)*(q[1].r-q[1].l);
    if(ans1[q[1].k]==0)
    ans2[q[1].k]=1;
    else{
        ll d=gcd(ans1[q[1].k],ans2[q[1].k]);
        ans1[q[1].k]/=d;
        ans2[q[1].k]/=d;
    }
    for(i=2;i<=m;i++){
        while(q[i].l<l)
        add(--l);
        while(q[i].r>r)
        add(++r);
        while(q[i].l>l)
        sub(l++);
        while(q[i].r<r)
        sub(r--);
        ans1[q[i].k]=res-(q[i].r-q[i].l+1);
        ans2[q[i].k]=(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
        if(ans1[q[i].k]==0)
         ans2[q[i].k]=1;
    else{
        ll d=gcd(ans1[q[i].k],ans2[q[i].k]);
        ans1[q[i].k]/=d;
        ans2[q[i].k]/=d;
    }
    }
    for(i=1;i<=m;i++){
        cout<<ans1[i]<<"/"<<ans2[i]<<endl;
    }
    
}
View Code

 

posted @ 2020-01-31 17:17  朝暮不思  阅读(136)  评论(0编辑  收藏  举报