[CodeForces] CF993E Nikita and Order Statistics

Subject to the effect

A given length of \ (n-\) sequence \ (a_i \) and \ (X \)
you need to find \ (ans_i \)
\ (ans_i \) represents the number of sections meet there \ (I \) number less than \ (X \)

answer

It is clear that the series only two types of number greater than or equal \ (x \) and less than \ (x \) the number of two kinds you may wish to \ (\ geq x \) is set to \ (0 \) other set \ (1 \ ) then \ (ans_i \) indicated that the number of intervals to meet \ (S_k - S_j = i \) \ (S \) is not repeated here and prefixes

\ (O (n ^ 2) \) violence

\ (s_i - s_j = k \ ) This can obviously be used \ (two pointer \) do \ (O (n) \) scans the entire array is calculated for each of the words, but then the time complexity is \ (O (n ^ 2) \)

(O (n \ log n) \) \ n Solutions

\ (s_i - s_j = k \ ) we transpose \ (s_i - k = s_j \ ) we have for each \ (i \) We only ask how many \ (s_i - k \) can be so \ (ans_i = \ sum_ {k} ^ nf (i
) * f (ik) \) order \ (g (i) = f (ik) \) then \ (ans_i = \ sum f (
i) * g (i) \) we can use \ (FFT \) to optimize the algorithm
we can make \ (g (i) = f (ni) \) after it polynomial multiplication \ (ans_i \) is equal to \ (h (ni) \)

Code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <queue>

using namespace std;

template <typename T> void chkmax (T &x, T y) {x = x > y ? x : y;}
template <typename T> void chkmin (T &x, T y) {x = x > y ? y : x;}

typedef long long ll;

const int INF = 2139062143;

#define DEBUG(x) std::cerr << #x << " = " << x << std::endl

template <typename T> void read (T &x) {
    x = 0; bool f = 1; char ch;
    do {ch = getchar(); if (ch == '-') f = 0;} while (ch > '9' || ch < '0');
    do {x = x * 10 + ch - '0'; ch = getchar();} while (ch >= '0' && ch <= '9');
    x = f ? x : -x;
}

template <typename T> void write (T x) {
    if (x < 0) x = ~x + 1, putchar ('-');
    if (x > 9) write (x / 10);
    putchar (x % 10 + '0');
}

const int N = 2e5 + 7;
const double PI = acos (-1.0);

struct complex {
    double x, y;
    complex (double xx = 0, double yy = 0) {x = xx, y = yy;}
} f[N], g[N];

complex operator + (complex a, complex b) {return complex (a.x + b.x, a.y + b.y);}
complex operator - (complex a, complex b) {return complex (a.x - b.x, a.y - b.y);}
complex operator * (complex a, complex b) {return complex (a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}

int n, x, l, r[N], s[N];

void FFT (complex *a, int limit, int opt) {
    for (int i = 0; i < limit; i ++ ) if (i < r[i]) swap (a[i], a[r[i]]);
    for (int i = 1; i < limit; i <<= 1) {
        complex Wn = complex (cos (PI / i), opt * sin (PI / i));
        for (int j = 0; j < limit; j += (i << 1)) {
            complex w = complex (1, 0);
            for (int k = 0; k < i; k ++, w = w * Wn) {
                complex p = a[j + k], q = w * a[j + k + i];
                a[j + k] = p + q; a[j + k + i] = p - q;
            }
        }
    }
    if (opt == -1) for (int i = 0; i < limit; i ++ ) a[i].x = a[i].x / limit;
}

inline ll calc() {
    ll res = 0;
    for (int i = 1, p = 0; i <= n; ++ i ) {
        if (s[i] != s[i - 1]) p = i;
        res += i - p;
    }
    return res;
}
int main () {
    read (n); read (x);
    f[0].x ++ ;
    for (int i = 1, k; i <= n; i ++ ) read (k), s[i] = s[i - 1] + (k < x), f[s[i]].x ++ ;
    for (int i = 0; i <= n; i ++ ) g[i] = f[n - i];
    int limit = 1; while (limit <= n + n) limit <<= 1, l ++ ;
    for (int i = 0; i < limit; i ++ ) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));

    FFT (f, limit, 1); FFT (g, limit, 1);
    for (int i = 0; i < limit; i ++ ) f[i] = f[i] * g[i];
    FFT (f, limit, -1);
    write (calc ()); putchar (' ');
    for (int i = 1; i <= n; i ++ ) printf ("%lld ", (ll) (f[n - i].x + 0.5));
    return 0;
}

Guess you like

Origin www.cnblogs.com/Hock/p/12232687.html