Description:
Given a numerical sequence {ai} with a length of N, ask how many ascending subsequences with a length of 5 in total. (AI <10 ^ 9, n <= 50000)
Analysis:
Because the number range is largeDiscretization1 ~ An integer between N. The original A [] array is converted to the D [] array, where D [I] = J indicates that a [I] is the number smaller than J in the [] array.
AvailableDynamic PlanningTo describe this algorithm:
P starts from 0 to N, And I = d [p].F [I] [k] indicates the number of Ascending Sequences ending with the number I and with the length k.
F [I] [k] + = Σ f [J] [k-1] (1 <= j <I)
F [I] [1] = 1
Such a dynamic transfer equation can be used to find the correct solution, but the time complexity isO (N ^ 2).
This can be used hereTree ArrayTo optimize the algorithm. We can see that what is required during status transfer is 1 ~ The sum of F [J] [I-1] Between K-1. Meets the requirements of the tree Array application. Modify the definition of F [I] [k] so that it is applied to a tree array. Reduced time complexityO (nlogn)
Note:1. The largest group of data should exceed int64, so it should be calculated using a large number. 2. the AI in the input data may have the same elements. You must handle them carefully.
- /*
- Pku3378 crazy thairs
- */
- # Include <stdio. h>
- # Include <stdlib. h>
- # Include <string. h>
- # Define clr (a) memset (a, 0, sizeof ())
- # Define int64 bignum_t
- # Define N 50005
- /*************************************** *************/
- # Define DIGIT 4 // number of digits stored by an array element
- # Define DEPTH 10000 // DEPTH = 10 DIGIT
- # Define MAX 30 // array Length
- Typedef int bignum_t [MAX + 1];
- // Assign a value
- Void value (bignum_t a, char buf []) {
- Char ch;
- Int I, j;
- Memset (void *) a, 0, sizeof (bignum_t ));
- For (a [0] = strlen (buf), I = a [0]/2-1; I> = 0; I --)
- Ch = buf [I], buf [I] = buf [a [0]-1-i], buf [a [0]-1-i] = ch;
- For (a [0] = (a [0] + DIGIT-1)/DIGIT, j = strlen (buf); j <a [0] * DIGIT; buf [j ++] = '0 ');
- For (I = 1; I <= a [0]; I ++)
- For (a [I] = 0, j = 0; j <DIGIT; j ++)
- A [I] = a [I] * 10 + buf [I * DIGIT-1-j]-'0 ';
- For (;! A [a [0] & a [0]> 1; a [0] --);
- }
- // Output
- Void write (const bignum_t ){
- Int I, j;
- For (printf ("% d", a [I = a [0]), I --; I --)
- For (j = DEPTH/10; j/= 10)
- Printf ("% d", a [I]/j % 10 );
- Puts ("");
- }
- // Addition
- Void add (bignum_t A, const bignum_t B) {// high-precision number A + B, the result is in
- Int I;
- For (I = 1; I <= B [0]; I ++)
- If (A [I] + = B [I])> = depth)
- A [I]-= depth, a [I + 1] ++;
- If (B [0]> = A [0])
- A [0] = B [0];
- Else
- For (; A [I]> = depth & I <A [0]; A [I]-= depth, I ++, a [I] ++ );
- A [0] + = (a [0] + 1]> 0 );
- }
- /*************************************** *****************/
- Int n, m;
- Int A [n], B [N], d [N];
- Int64 f [N] [5];
- Int cmp (const void * I, const void * j ){
- Return a [* (int *) I]-a [* (int *) j];
- }
- Void Add (int I, int j, int64 t ){
- While (I <= m ){
- Add (f [I] [j], t );
- I + =-I & I;
- }
- }
- Void Sum (int I, int j, int64 s ){
- Char c0 [10] = "0 ";
- Value (s, c0 );
- While (I> 0 ){
- Add (s, f [I] [j]);
- I-=-I & I;
- }
- }
- Int main ()
- {
- While (scanf ("% d", & N )! = EOF ){
- Int I, J, K;
- // Input
- For (I = 0; I <n; I ++ ){
- Scanf ("% d", & A [I]);
- B [I] = I;
- }
- // Order
- Qsort (B, n, sizeof (B [0]), CMP );
- M = 1;
- D [B [0] = 1;
- For (I = 1; I <n; I ++ ){
- If (A [B [I]! = A [B [I-1]) m ++;
- D [B [I] = m;
- }
- // DP
- Int64 V1, T, U;
- Char C0 [10] = "0 ";
- Char c1 [10] = "1 ";
- Value (V1, C1 );
- For (k = 0; k <= m; k ++) {// CLR
- For (j = 0; j <5; j ++ ){
- Value (F [k] [J], C0 );
- }
- }
- For (k = 0; k <n; k ++) {/dp
- I = d [k];
- Add (I, 0, V1); // F [I] [0] = 1
- For (j = 1; j <= 4; j ++ ){
- Sum (I-1, J-1, T); // F [J] T = sum (I-1)
- Add (I, j, T); // F [] [J] add (I, T)
- }
- }
- // Total
- Int64 total;
- Sum (m, 4, total );
- // Output
- Write (total );
- }
- Return 0;
- }