1. 程式人生 > >BZOJ 2038 小Z的襪子 莫隊

BZOJ 2038 小Z的襪子 莫隊

注意一些量的初始化,sum ,L,R,UP 這類的
注意區間先擴後增

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn=50005;
int c[maxn];
LL num[maxn];
int n,m;
LL ans1[maxn],ans2[maxn];
struct node{
    int l,r,id;
}Q[maxn];
int pos[maxn];
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]; } LL gcd(LL a,LL b){ return b==0?a:gcd(b,a%b); } int L,R; LL UP,DOWN,sum; LL C(LL x){ return x*(x-1)/2; } void add(int x){ if(num[c[x]]){ UP+=C(num[c[x]]+1)-C(num[c[x]]); } num[c[x]]++; sum++; } void del(int x){ if(num[c[x]]>=2
){ UP-=C(num[c[x]])-C(num[c[x]]-1); } num[c[x]]--; sum--; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&c[i]); } int sz=sqrt(n); for(int i=1;i<=m;i++){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; pos[i]=i/sz; } L=1
,R=1,UP=0,sum=1; memset(num,0,sizeof(num)); num[c[1]]=1; sort(Q+1,Q+1+m,cmp); for(int i=1;i<=m;i++){ while(R<Q[i].r){ R++; add(R); } while(L>Q[i].l){ L--; add(L); } while(R>Q[i].r){ del(R); R--; } while(L<Q[i].l){ del(L); L++; } DOWN=C(sum); if(UP==0){ ans1[Q[i].id]=0; ans2[Q[i].id]=1; continue; } LL d=gcd(UP,DOWN); ans1[Q[i].id]=UP/d;; ans2[Q[i].id]=DOWN/d; } for(int i=1;i<=m;i++){ printf("%lld/%lld\n",ans1[i],ans2[i]); } return 0; }