莫队算法,进行组合数转换,就能发现贡献度只要维护平方和就行
网上有很多好题解,我只是记录一下我的代码
注意本题两个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; } }