Before I write this blog, one of the things I want to do most is: Orz mo team%%%%%%%%.
Description: Ceil (x) indicates X-Rounding, and sqrt (x) represents the square root of the X-squared.
First, MO team algorithm Introduction
MO Team algorithm is a kind of brute force algorithm, really violent, but fast, belongs to the fast violence. Its basic idea is to divide the blocks. Refer to Hzwer's blog for recommendations on chunking, then%%%%hzw. MO Team algorithm is mainly used to solve the problem of a class of offline query, and the problem of line tree processing is the same, but the processing is two different aspects, when transferred from [L,r] to [L ', R '] time is O (| L '-l|+| R '-r|) It is advisable to use the MO team algorithm . This can be learned from the topic. Because the block is taken, its complexity is O (nsqrt (n)). The essence is to be asked in a certain order, this should also be understood from the topic, we refer to a topic.
Ii. Typical examples
Famous example, Little Z's socks
Links: http://www.lydsy.com/JudgeOnline/problem.php?id=2038
The topic is Chinese, can understand so do not copy paste. Test instructions is not difficult to understand, a little combination of mathematical knowledge can be seen.
Third, the solution
Because the combination of the topic is C (n,2), so we preprocess the C2 array, storing 2-n to 2 of the combined number, as a special case, C (0,2) =c () = 0;
We use the Bucket tab to store the number of each color in [l,r], assuming we find [l,r], [l+1,r] (or [l-1,r][l,r+1][l,r-1]) only need to put in the bucket-or + + can be, so [l,r] answer is ans, then [l+1,r] The answer is ans-c (tab[l],2) +c (tab[l]+1,2), which is O (1);
We can see that, assuming we have [l,r], we find the time of [L ', R '] O (| L '-l|+| R '-r|), so we use the MO team algorithm.
The data range is n,m<=50000, which inspires us to use chunking (of course, if you insist on writing Manhattan's smallest spanning tree, then no one will stop you). Let's start with all the queries according to L as the first keyword, R for the second key word order, and then divide the ordered array into [√n] block, and then divide the good block of the array according to the R size of the order, so we finished the first step.
Then we do the block, for each piece, find out each query and it before a query of the difference, modify the differences, and constantly do so, you can get the answer.
The total time complexity is only O (n√n), much faster than the original O (n^2) violence, but why?
Iv. Analysis of Complexity
The first is the chunking step, the time complexity of this step is undoubtedly O (√n*√n*log√n+nlogn) =o (NLOGN);
Then came to the essence of the MO team algorithm, below we use the easy-to-understand middle school method to prove its time complexity is O (n√n);
The maximum value of l in each piece is Max1,max2,max3,..., maxceil (√n).
By the first order, Max1<=max2<=...<=maxceil (√n)
Obviously, the time for each piece of violence to seek out the first inquiry is the complexity of O (n).
Consider the worst case, in each piece, the maximum value of R is N, and each modification operation is to modify L from Maxi-1 to Maxi or maxi to maxi-1.
Consider R: Because R is already sequenced in the block, the time complexity of modifying it in the same piece is O (n). For all blocks is O (n√n).
Focus Analysis L: Because the time complexity of each change is O (maxi-maxi-1), the time complexity in the same piece is O (√n* (maxi-maxi-1)).
Combine the time complexity of each piece of L to get the total time complexity for L
O (√n* (max1-1) +√n* (max2-max1) +√n* (MAX3-MAX2) +...+√n* (Maxceil (√n)-maxceil (√n-1)))
=o (√n* (Max1-1+max2-max1+max3-max2+...+maxceil (√n-1)-maxceil (√n-2) +maxceil (√n)-maxceil (√n-1)))
=o (√n* (Maxceil (√n)-1)) (middle school split sum)
It is known from the problem that Maxceil (√n) is the largest of n, so the total time complexity of L is the worst case O (n√n).
In summary, MO Team algorithm time complexity is O (n√n);
V. Example code
Or with Emacs write, so still two indentation, do not like to spray.
1#include <bits/stdc++.h>2 using namespacestd;3typedefLong Longll;4ll a[60000],tab[60000];5 structask{6 ll L,r,num;7}b[60000];8 ll CMP (ask X,ask y) {9 if(X.L<Y.L)return 1;Ten if(X.L>Y.L)return 0; One if(X.R<Y.R)return 1; A return 0; - } - ll Comp (ask X,ask y) { the if(X.R<Y.R)return 1; - if(X.R>Y.R)return 0; - if(X.L<Y.L)return 1; - return 0; + } - ll gcd (ll A,ll b) { + if(!B)returnA; A returnGCD (b,a%b); at }ll n,m; -ll comb2[60000];//combination number C (n,2) -ll prix[60000],priy[60000];//Answer -LL Rep (ll Ol,ll nl,ll lr,ll nr,ll&ans) {//answer the question of the modification, the original is [OL,LR], now is [nl,nr];27 if(ol<=NL) - for(ll i=ol;i<nl;i++) {Ans-=comb2[tab[a[i]]; tab[a[i]]--;ans+=Comb2[tab[a[i]];} in Else - for(LL i=ol-1; i>=nl;i--) {ans-=comb2[tab[a[i]]; tab[a[i]]++;ans+=Comb2[tab[a[i]];} to for(LL i=lr+1; i<=nr;i++) {ans-=comb2[tab[a[i]]; tab[a[i]]++;ans+=Comb2[tab[a[i]];} + returnans; - } the * intMain () { $scanf"%lld%lld", &n,&m); comb2[1]=comb2[0]=0;Panax Notoginseng for(LL i=2; i<=n;i++) comb2[i]= (LL) ((Double) i/2.0*(Double) (I-1)); //calculation combination number - for(LL i=1; i<=n;i++) scanf ("%lld",&a[i]); the for(LL i=1; i<=m;i++){ +scanf"%lld%lld",&b[i].l,&B[I].R); Ab[i].num=i; the } +ll sq=sqrt (m); -Sort (b +1, b+m+1, CMP); //First-time sort $ for(LL i=1; i<=m;i+=sq) { $Sort (B+i,b+min (i+sq,m+1), comp); //Second order - } - for(LL i=1; i<=m;i+=sq) { thell Ed=min (m,i+sq-1); -memset (tab,0,sizeof(tab)); ll maxx=0;Wuyi Long Longans=0; Ans=rep (b[i].l,b[i].l,b[i].l-1, B[i].r,ans); //Same down theprix[b[i].num]=ans;priy[b[i].num]=comb2[b[i].r-b[i].l+1]; //violence to figure out the first of each piece, actually here can not do so, directly inherit the last piece also line - if(prix[b[i].num]==0) priy[b[i].num]=1; Wu Else{ll g=gcd (Prix[b[i].num],priy[b[i].num]); -Prix[b[i].num]/=g;priy[b[i].num]/=G;} //Numerator About for(LL j=i+1; j<=ed;j++){ $Prix[b[j].num]=rep (b[j-1].l,b[j].l,b[j-1].r,b[j].r,ans); //Derive this inquiry from the previous inquiry -priy[b[j].num]=comb2[b[j].r-b[j].l+1]; - if(prix[b[j].num]==0) priy[b[j].num]=1; - Else{ All g=gcd (Prix[b[j].num],priy[b[j].num]); +Prix[b[j].num]/=g;priy[b[j].num]/=G; the } - } $ } the for(LL i=1; i<=m;i++){ theprintf"%lld/%lld\n", Prix[i],priy[i]); //need attention here, Bzoj has a pit, cout will re the } the return 0; -}
MO Team algorithm and its application