BZOJ 2038 莫隊演算法
阿新 • • 發佈:2018-12-11
對於一個區間詢問[L,R],我們要求的ans是
ans=Σ[(sum(color[i])−1)∗sum(color[i])/2)]/[((R−L+1)∗(R−L))/2]
化簡ans=(Σ-(R-L+1))/((R-L+1)*(R-L))
sum(color[i])時第i種顏色在[L,R]中出現的次數
我們只要更新的值就好了
#include<bits/stdc++.h> using namespace std; #define N 2300010 #define ll long long const int maxn=50005; int n,m,pos[maxn],c[maxn]; ll s[maxn],ans; ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } struct Query { int l,r,id; ll a,b; }a[maxn]; bool cmp(Query a,Query b) { if(pos[a.l]==pos[b.l]) return a.r<b.r; return a.l<b.l; } bool cmp_id(Query a,Query b) { return a.id<b.id; } void update(int p,int add) { ans-=s[c[p]]*s[c[p]]; s[c[p]]+=add; ans+=s[c[p]]*s[c[p]]; } int main(){ scanf("%d%d",&n,&m); int k=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<=n;i++) pos[i]=(i-1)/k+1; for(int i=1;i<=m;i++) { scanf("%d%d",&a[i].l,&a[i].r); a[i].id=i; } sort(a+1,a+1+m,cmp); for(int i=1,l=1,r=0;i<=m;i++) { for(;r<a[i].r;r++) update(r+1,1); for(;r>a[i].r;r--) update(r,-1); for(;l<a[i].l;l++) update(l,-1); for(;l>a[i].l;l--) update(l-1,1); if(a[i].l==a[i].r) { a[i].a=0; a[i].b=1; continue; } a[i].a=ans-(a[i].r-a[i].l+1); a[i].b=(ll)(a[i].r-a[i].l+1)*(a[i].r-a[i].l); ll kk=gcd(a[i].a,a[i].b); a[i].a/=kk; a[i].b/=kk; } sort(a+1,a+1+m,cmp_id); for(int i=1;i<=m;i++) printf("%lld/%lld\n",a[i].a,a[i].b); return 0; }