Reprint please indicate the source, thank you http://blog.csdn.net/ACM_cxlove? Viewmode = contents by --- cxlove
Question: N numbers are given, three numbers are selected, and an equal difference series is formed by subscript.
Http://www.codechef.com/problems/COUNTARI
It is not difficult to form only an arithmetic difference series. It is probably a convolution first, and then O (n) Enumeration to judge the number of 2 * A [I], but it won't be done according to the subscript.
There is a very distinct number, probably the number in the middle of the O (n) enumeration, and then convolution on both sides, O (N * n * lgn ).
If you can think of the number in the middle of the enumeration, you should be able to further think of Block Processing.
If it is divided into k blocks
There are several situations:
If the three numbers are in the current block, you can enumerate the last two numbers to find the first number and the complexity O (N/K * n/K)
If the two numbers are in the current block, the other number may be in the front or the back. Similarly, we can enumerate the two numbers for search and complexity.
O (N/K * n/K)
If there is only one number in the current block, perform convolution on the numbers on both sides, enumerate the number in the current block, and query 2 × A [I]. Complexity O (N * lg n)
Then the total is O (K * (N/K * n/K + N * LG n )).
# Include <iostream> # include <cstdio> # include <cstring> # include <cmath> # include <algorithm> using namespace STD; // FFT copy from kuangbinconst double Pi = ACOs (-1.0); // complex z = a + B * I struct Complex {double A, B; complex (double _ A = 0.0, double _ B = 0.0): A (_ A), B (_ B) {} complex operator + (const complex & C) const {return complex (A + C. a, B + C. b);} complex operator-(const complex & C) const {return complex (a-c. a, B-c. b);} complex operator * (const complex & C) const {return complex (A * C. a-B * C. b, A * C. B + B * C. a) ;}}; // Len = 2 ^ kvoid change (complex y [], int Len) {for (INT I = 1, j = Len/2; I <len-1; I ++) {if (I <j) Swap (Y [I], Y [J]); int K = Len/2; while (j> = k) {J-= K; k/= 2;} If (j <k) J + = K ;}} // FFT // Len = 2 ^ K // on = 1 DFT on =-1 idftvoid FFT (complex y [], int Len, int on) {change (Y, len); For (int h = 2; H <= Len; H <= 1) {complex Wn (COS (-on * 2 * PI/h ), sin (-on * 2 * PI/H); For (Int J = 0; j <Len; j + = h) {complex W (1, 0 ); for (int K = J; k <j + H/2; k ++) {complex u = Y [k]; complex T = W * Y [K + H/2]; y [k] = u + T; y [K + H/2] = u-t; W = W * wn ;}}if (on =-1) {for (INT I = 0; I <Len; I ++) {Y [I]. a/= Len ;}} const int n = 100005; typedef long ll; int n, a [n]; int block, size; ll num [n <2]; int min_num = 30000, max_num = 1; int before [N] = {0}, behind [N] = {0 }, in [N] = {0}; complex X1 [n <2], X2 [n <2]; int main () {# ifndef online_judge freopen ("input.txt ", "r", stdin); # endif scanf ("% d", & N); For (INT I = 0; I <n; ++ I) {scanf ("% d", & A [I]); behind [A [I] ++; min_num = min (min_num, a [I]); max_num = max (max_num, a [I]);} ll ret = 0; block = min (n, 35); size = (n + block-1)/block; for (int t = 0; t <block; t ++) {int S = T * size, E = (t + 1) * size; If (E> N) E = N; For (INT I = s; I <E; I ++) {behind [A [I] --;} For (INT I = s; I <E; I ++) {for (Int J = I + 1; j <E; j ++) {int m = 2 * A [I]-A [J]; If (M> = 1 & M <= 30000) {// both of three in the block RET + = in [m]; // One of the number in the PRE block RET + = before [m];} m = 2 * A [J]-A [I]; If (M> = 1 & M <= 30000) {// One of the number in the next block RET + = behind [m];} in [A [I] ++;} // pre block, current block, next block if (T> 0 & T <block-1) {int L = 1; int Len = max_num + 1; while (L <Len * 2) L <= 1; for (INT I = 0; I <Len; I ++) {x1 [I] = complex (before [I], 0 );} for (INT I = Len; I <L; I ++) {x1 [I] = complex (0, 0) ;}for (INT I = 0; I <Len; I ++) {X2 [I] = complex (behind [I], 0) ;}for (INT I = Len; I <L; I ++) {X2 [I] = complex (0, 0);} FFT (x1, L, 1); FFT (X2, L, 1); For (INT I = 0; I <L; I ++) {x1 [I] = x1 [I] * X2 [I];} FFT (x1, L,-1 ); for (INT I = 0; I <L; I ++) {num [I] = (LL) (x1 [I]. A + 0.5) ;}for (INT I = s; I <E; I ++) {RET + = num [A [I] <1] ;}} for (INT I = s; I <E; I ++) {in [A [I] --; before [A [I] ++ ;}} printf ("% LLD \ n", RET); Return 0 ;}