Binary Index Tree and segment tree for PKU #3378 crazy thairs

Source: Internet
Author: User
Tags bit definition
Crazy thairs
Time limit:3000 Ms Memory limit:65536 K
Total submissions:3111 Accepted:699

Description

These days, sepageris crazed on one problem named Crazy Thair. GivenN(1 ≤N≤ 50000) numbers, which are no more than 109, crazy Thair is a group of 5 numbers {I,J,K,L,M} Satisfying:

1. 1 ≤I<J<K<L<MN
2.AI<AJ<AK<Al<AM

For
Example, in the sequence {2, 1, 3, 4, 5, 7, 6}, there are four crazy
Thair groups: {1, 3, 4, 5, 6}, {2, 3, 4, 5, 6}, {1, 3, 4, 5, 7} and {2,
3, 4, 5, 7 }.

Cocould you help sepr to count how many crazy thairs in the sequence?

Input

Input contains several test cases. Each test case begins with a line containing a numberN, Followed by a line containingNNumbers.

Output

Output The amount of crazy thairs in each sequence.

Sample Input

5
1 2 3 4 5
7
2 1 3 4 5 7 6
7
1 2 3 4 5 6 7

Sample output

1
4
21

Source

Poj monthly -- 2007.09.09, tdzl2003 recently saw a line segment tree. When I encountered the above question, I had a chance to display it. analysis: If you want to know the number of 5 consecutive increments, we will start from two, and then expand to three and the last five. if we use the table to represent the data, we will get a table like this: (we select 2 1 3 4 5 7 6 as an example)
number: 2 1 3 4 5 7 6
1: 1 1 1 1 1 12: 0 0 2 3 4 5 53: 0 0 0 2 5 9 94: 0 0 0 2 7 75: 0 0 0 0 2 2 so the number of crazy thairs is 5. from here we can find the law below F (I, K) = Sigma F (I-1, k-1), that is to say for a certain K, the number of consecutive I incremental data is the sum of the K-1 continuous incremental data. therefore, it is easy to think of the number of line segments as a good idea. each time we insert data with a certain degree of authority, it is completely applicable to this situation. the idea here is 1. first, choose one nlogn sorting method. (obtain the location information (idx) of each number relative to the sorted value) 2. insert each pair of idx arrays to the number of line segments to obtain a new set of values. number of Inserted Line Segments in a loop. (from 1-2, 2-3, 3-4, 4-5. accumulate the number of 5, pay attention to the large number (greater than int64) // note, the code here is not complete code: // If find, return the index, else return-1; <br/> int binraysearch (int A [], int length, int V) <br/>{< br/> int L = 0; <br/> int r = length-1; <br/> int mid = 0; <br/> bool find = false; <br/> while (L <= r) <br/>{< br/> mid = (L + r)> 1; <br/> if (a [Mid] <v) <br/>{< br/> L = Mid + 1; <br/>}< br/> else if (a [Mid]> V) <br/>{< br/> r = mid-1; <br/>}< br/> else <br/> {<br/> // find; <br/> Find = true; <br/> break; <br/>}< br/> If (FIND) <br/> return mid; <br/> else <br/> return-1; <br/>}< br/> # define array_length 50000 <br/> void calbysegmenttree (int * pidx, long * ps, long * PD, int N) <br/> {<br/> long * PT = new long [(n + 1) * 4]; <br/> memset (PT, 0, sizeof (long) * (n + 1) * 4); <br/> for (INT I = 0; I <n; I ++) <br/>{< br/> int L = 0; <br/> int r = n-1; <br/> int n = 1; <br/> long s = 0; <br/> int v = pidx [I]; <br/> while (L <R) <br/>{< br/> int mid = (L + r)> 1; <br/> If (V> mid) <br/>{< br/> // plus current Tree node value, means all left nodes are counted <br/> S + = PT [N]; <br/> L = Mid + 1; <br/> // right child node, n = 2 * n + 1; <br/> N = (n <1); <br/> N ++; <br/>}< br/> else <br/> {<br/> // left child node <br/> r = mid; <br/> PT [N] + = Ps [I]; <br/> N = (n <1 ); <br/>}< br/> S + = PT [N]; <br/> Pd [I] = s; <br/> PT [N] + = Ps [I]; <br/>}< br/> Delete [] PT; <br/>}< br/> bool calculate (int * parray, int N, int grouplength/* Crazy Thair is a group of 5 numbers, so here it's 5 */) <br/> {<br/> int * pb = new int [N]; <br/> memcpy_s (Pb, N * sizeof (INT), parray, sizeof (INT) * n); <br/> mylib: mergesort (parray, N ); <br/> long * PS = new long [N]; <br/> long * Pd = new long [N]; </P> <p> int * pidx = new int [N]; <br/> for (INT I = 0; I <n; I ++) <br/> {<br/> PS [I] = 1; <br/> Pd [I] = 0; <br/> pidx [I] = binraysearch (parray, n, Pb [I]); <br/>}< br/> for (INT I = 0; I <groupLength-1; I ++) <br/>{< br/> calbysegmenttree (pidx, PS, PD, n); <br/> long * ptemp = Ps; <br/> PS = Pd; <br/> Pd = ptemp; <br/> memset (PD, 0, sizeof (long) * n ); <br/>}</P> <p> long ans1 = 0, ans2 = 0; <br/> for (INT I = 0; I <N; I ++) <br/>{< br/> ans1 + = (ans2 + PS [I])/commandid 201710000ll; <br/> ans2 = (ans2 + PS [I]) % has been created before ll; <br/>}< br/> If (ans1) <br/>{< br/> STD: cout <ans1; <br/> STD: cout <ans2 <STD: Endl; <br/>}< br/> else <br/> STD: cout <ans2 <STD: Endl; <br/> return true; <br/>}From the perspective of personal sentiment, it is a usable solution, but the problem lies in the various long * ptree = new long [(nlength + 1) * 4] brought by the number of line segments; the overhead is also very dazzling. (we all know that the size of the Line Segment here is 2*2 [logn] + 1) If we want to fix this overhead, we can replace it with a more practical bit (Binary Index Tree). Here the bit definition can go to the http://www.topcoder.com/tc? Module = static & d1 = tutorials & D2 = binaryindexedtrees find the definition. Our specific solution is: # Define array_length 50000 <br/> bool calculatebit (int * parray, int N, int grouplength/* Crazy Thair is a group of 5 numbers, so here it's 5 */) <br/> {<br/> int * pb = new int [N]; <br/> memcpy_s (Pb, N * sizeof (INT), parray, sizeof (INT) * n); <br/> mylib: mergesort (parray, n); <br/> long * PS = new long [N]; <br/> long * Pd = new long [N]; <br/> int * pidx = new int [N]; <br/> for (INT I = 0; I <n; I ++) <br/>{< br/> PS [I] = 1; <br/> Pd [I] = 0; <br/> pidx [I] = binraysearch (parray, N, Pb [I]); <br/>}< br/> mylib: binaryindextree <long, array_length> bit; </P> <p> for (INT I = 0; I <groupLength-1; I ++) <br/>{< br/> for (INT I = 0; I <n; I ++) <br/> {<br/> Pd [I] = bit. read (pidx [I]); <br/> bit. update (pidx [I], PS [I]); <br/>}< br/> bit. clear (); <br/>{< br/> // exchange A and R; <br/> long * ptemp = Ps; <br/> PS = Pd; <br/> Pd = ptemp; <br/> memset (PD, 0, sizeof (long) * n ); <br/>}</P> <p> long ans1 = 0, ans2 = 0; <br/> for (INT I = 0; I <n; I ++) <br/>{< br/> ans1 + = (ans2 + PS [I])/explain ll; <br/> ans2 = (ans2 + PS [I]) % has been created before ll; <br/>}< br/> If (ans1) <br/>{< br/> STD: cout <ans1; <br/> STD: cout <ans2 <STD: Endl; <br/>}< br/> else <br/> STD: cout <ans2 <STD: Endl; </P> <p> return true; <br/>}Replace the original function with a new one, and then use a bit template. Currently, only read and update functions are available. The following is the definition of this template: # Pragma once <br/> namespace mylib <br/>{< br/> template <class t, int maxval> class binaryindextree <br/>{</P> <p> Public: <br/> binaryindextree (); <br/> ~ Binaryindextree (); <br/> // The Real idx cocould start from 0-max. <br/> // here we have to transfer to 1-max + 1 for calculation <br/> void Update (INT idx, t Val); // update the T (tree) array <br/> t read (INT idx); // read the <br/> void clear (); <br/> PRIVATE: <br/> T * t; <br/>}; <br/> template <class T, int maxval> binaryindextree <t, maxval >:: binaryindextree () <br/>{< br/> T = new T [maxval + 1]; <br/> memset (t, 0, (maxval + 1) * sizeof (t); <br/>}< br/> template <class T, int maxval> binaryindextree <t, maxval> ::~ Binaryindextree () <br/>{< br/> Delete [] T; <br/>}< br/> template <class T, int maxval> void binaryindextree <t, maxval >:: Update (INT idx, t Val) <br/>{< br/> idx ++; <br/> while (idx <= maxval + 1) {<br/> T [idx] + = val; <br/> idx + = (idx &-idx ); <br/>}</P> <p> template <class T, int maxval> T binaryindextree <t, maxval>: Read (INT idx) <br/> {<br/> idx ++; <br/> T sum = 0; <br/> while (idx> 0) {<br/> sum + = T [idx]; <br/> idx-= (idx &-idx); <br/>}< br/> return sum; <br/>}< br/> template <class T, int maxval> void binaryindextree <t, maxval >:: clear () <br/>{< br/> memset (T, 0, (maxval + 1) * sizeof (t); <br/>}< br/> };One thing to note is the idx value range. I am very inclined to start from 1 to Max + 1, rather than 0-max... external calls are generally in the range of 0-Max, so we have made a special note here. the template is used here to consider whether there will be a more general situation and can be extended. but after writing it, it seems that there is no: (no matter how good it is, it can work, and it is more efficient than the number of line segments! There is less space to use. Appendix: this type of question is purely for the sake of recreation. You can play it casually, and your level is not good.

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.