MO Team Algorithm Conscience explanation

Source: Internet
Author: User

Problem: There are n number of a sequence, there is m shape such as Ask L, R Inquiry, each query need to answer the number of at least 2 times in the interval.

The simple solution requires reading the number of O (nm). If you use the STL map to save the number of occurrences, the complexity of O (NMLOGN) is required each time. Is there a quicker way?

Note that the inquiry is not mandatory online, so we can use the offline method. Note that if we have a map that calculates [L, R], then [L-1, R], [L + 1, R], [L, R-1], [L, R + 1] can be obtained in the complexity of O (Logn). If you can arrange the appropriate order of inquiry so that each query can use the last map, then we will be able to complete the inquiry in a more sophisticated degree.

How do you arrange the inquiry? One way is to sort by the left endpoint and then sort by the right endpoint. The complexity of sorting is O (MLOGM). The left point movement is only O (n), but the right end of each query to move o (n), a total of M queries, so the total number of moves O (nm), the overall move o (MLOGM + nm), and then the STL O (LOGN), the upper operating time is not reduced.

The MO team algorithm is a good way to solve the above problems. The MO team algorithm thinks that after the left endpoint is sorted, the left end of the terminal movement must be few, but the right endpoint moves much more often. If you reduce the number of right end moves appropriately, even a little bit more left end-point moves can be cost-effective in total complexity.

The MO team algorithm first divides the entire sequence into √n blocks (just conceptually divided blocks, in fact we do not need to store anything other than the block size), sorting each query according to the block ordinal (same as the right endpoint sort). After that, we start by sorting through the first query to solve the sub-problem in turn.

intLen;
structquery{intL, R, ID, block; Query () {} query (intLintRintID): L (L), R (r), ID (ID) {Block= L/Len; } BOOL operator< (ConstQuery RHS)Const { if(block = = Rhs.block)returnR <RHS. R returnBlock <Rhs.block; }}queries[maxm];map<int,int>Buf;inlinevoidInsertintN) {
if (Buf.count (n))
++Buf[n];
Else
Buf[n] = 1;
}inlinevoidEraseintN) {
if (--buf[n] = = 0) buf.erase (n);
}intA[MAXN]; Original sequence Queue<int>ANSS[MAXM]; Storing answersintMain () {intN, M; CIN>>N; Len= (int) sqrt (n); for(inti =1; I <= N; i++) {cin>>A[i]; } CIN>>m; for(inti =1; I <= m; i++){ intL, R; CIN>> L >>R; Queries[i]=Query (L, R, I); } Sort (Queries+1, queries + M +1); intL =1, R =1; buf[a[1]] =1; for(inti =1; I <= m; i++) {Queue<int>& ans =Anss[queries[i].id]; while(R < queries[i]. R) Insert (a[++R]); while(R > Queries[i]. R) Erase (a[r--]); while(L < queries[i]. L) Erase (a[l++]); while(L > Queries[i]. L) Insert (a[--L]); for(map<int,int>::iterator it = Buf.begin (); It! = Buf.end (); ++it) { if(It->second >=2) {Ans.push (it-First ); } } } for(inti =1; I <= m; i++) {Queue<int>& ans =Anss[i]; while(!Ans.empty ()) {cout<< Ans.front () <<' '; Ans.pop (); } cout<<Endl; }}

Although we split the block, we can treat all the "ask transfer" equally. The code above has three places to be aware of. The first is insert and erase, here before inserting to determine whether the existence, after inserting to determine whether it is 0. This is not necessary (insert will initialize the new node to 0,erase to 0 after the processing answer does not affect), the second is the order of interval changes, the insert is best placed in front, erase best in the back (think, why); the third is that the insert always uses the prefix increment-decrement operator. Erase always uses the suffix operator.

How complex is the team's time? We classify the issues into discussion.

The current query is in the same block as the previous query left endpoint, then the left endpoint is moved to O (n0.5). Although the right endpoint movement may be up to O (n), the sum of the right end points of the whole piece of inquiry is also O (n) (think about it, why). So the whole block moves to O (m0.5) XO (n0.5) + O (n), there are m0.5 blocks, and the time complexity is O (mn0.5+nm0.5).

When asked the left endpoint is not in the same block as the previous query, then the left endpoint moves to O (n0.5), but the right endpoint moves up to O (n). Fortunately, this situation is only O (n0.5), and the time complexity is O (n1.5).

The total number of moves is O (n1.5+m0.5n+mn0.5), because with map, the total time complexity is also multiplied by an O (Logn) on the total number of moves.

MO Team Algorithm Conscience explanation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.