【莫队算法】
〖相关资料〗
〖相关题目〗
1.【bzoj2038】[2009国家集训队]小Z的袜子(hose)
题意:给出n个数与m个区间,在每个区间内选出两个数,求选出的两个数相等的概率。
分析:hzwerの博客
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #define LL long long 6 using namespace std; 7 const int N=5e4+5; 8 int n,m,s[N],c[N],pos[N]; 9 LL ans; 10 struct node{int id,l,r;LL a,b;}a[N]; 11 int read() 12 { 13 int x=0,f=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 15 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 16 return x*f; 17 } 18 bool cmp(node a,node b) 19 { 20 if(pos[a.l]==pos[b.l])return a.r<b.r; 21 return a.l<b.l; 22 } 23 bool cmp2(node a,node b){return a.id<b.id;} 24 LL sqr(int x){return 1ll*x*x;} 25 LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);} 26 void update(int p,int val) 27 { 28 ans-=sqr(s[c[p]]); 29 s[c[p]]+=val; 30 ans+=sqr(s[c[p]]); 31 } 32 int main() 33 { 34 n=read();m=read(); 35 for(int i=1;i<=n;i++)c[i]=read(); 36 int block=(int)sqrt(n); 37 for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1; 38 for(int i=1;i<=m;i++) 39 a[i].l=read(),a[i].r=read(),a[i].id=i; 40 sort(a+1,a+m+1,cmp); 41 for(int i=1,l=1,r=0;i<=m;i++) 42 { 43 for(;r<a[i].r;r++)update(r+1,1); 44 for(;r>a[i].r;r--)update(r,-1); 45 for(;l<a[i].l;l++)update(l,-1); 46 for(;l>a[i].l;l--)update(l-1,1); 47 if(a[i].l==a[i].r){a[i].a=0;a[i].b=1;continue;} 48 a[i].a=ans-(a[i].r-a[i].l+1); 49 a[i].b=1ll*(a[i].r-a[i].l+1)*(a[i].r-a[i].l); 50 LL k=gcd(a[i].a,a[i].b); 51 a[i].a/=k;a[i].b/=k; 52 } 53 sort(a+1,a+m+1,cmp2); 54 for(int i=1;i<=m;i++)printf("%lld/%lld\n",a[i].a,a[i].b); 55 return 0; 56 }