E. Nikita and Order Statistics
solution
求任意区间内小于 x x x 的元素个数,并按顺序输出 k = 0.. n k=0..n k=0..n 的区间数.
记录前缀和 a n s [ i ] ans[i] ans[i] 表示前 i i i 个数里小于 x x x 的元素个数.
区间 l , r l,r l,r 内小于 x x x 的元素个数为 a n s [ r ] − a n s [ l − 1 ] ans[r] - ans[l - 1] ans[r]−ans[l−1],即 x a n s [ r ] − a n s [ l − 1 ] x^{ans[r]-ans[l-1]} xans[r]−ans[l−1] 的系数.
由于 − a n s [ l − 1 ] -ans[l-1] −ans[l−1] 是负数,我们将其 + n +n +n 处理,就变成了 x a n s [ r ] + ( n − a n s [ l − 1 ] ) x^{ans[r]+(n - ans[l-1])} xans[r]+(n−ans[l−1]).
得到 ∑ x i ∗ x n − i \sum x^i * x^{n - i} ∑xi∗xn−i,FFT之后得到的第 n + k n+k n+k 次项的系数,即小于 x x x 的元素个数为 k k k 的区间个数.
由于卷积的同时,会遇到 x k + ( n − k ) x^{k+(n-k)} xk+(n−k) 的状况,即 k = 0 k=0 k=0 的项会多 ( n + 1 ) (n+1) (n+1) 次,我们将其减去,又因为 x i x^i xi 和 x n − i x^{n-i} xn−i 重复了一遍,再除以2,得到 [ x 0 ] − n − 1 2 \frac{[x^0] - n - 1}{2} 2[x0]−n−1.
code
/*SiberianSquirrel*//*CuteKiloFish*/
#include <bits/stdc++.h>
using namespace std;
#define gcd(a,b) __gcd(a,b)
#define Polynomial vector<ll>
#define Inv(x) quick_pow(x, mod - 2)
#define DEBUG(x, y) cout << x << ": " << y << '\n';
#define rep(i, a, b) for(int i = a; i <= b; ++ i)
#define per(i, a, b) for(int i = a; i >= b; -- i)
#define mem(x, a) memset(x, a, sizeof x)
using ld = long double;
using ll = long long;
using ull = unsigned long long;
//const ll mod = 998244353, mod_g = 3, img = 86583718;
const ll mod = 1004535809, mod_g = 3;
const int N = int(1e5 + 10);
template<typename T> inline T read() {
T x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
template<typename T> inline T print(T x) {
if(x < 0) { putchar('-'); x =- x; }
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
const ld pi = acos(-1.0);
struct Complex {
ld r, i;
Complex(ld _r = 0, ld _i = 0) : r(_r), i(_i) {}
Complex operator + (const Complex &b) const {
return Complex(r + b.r, i + b.i);
}
Complex operator - (const Complex &b) const {
return Complex(r - b.r, i - b.i);
}
Complex operator * (const Complex &b) const {
return Complex(r * b.r - i * b.i, r * b.i + i * b.r);
}
Complex operator / (const Complex &b) const {
return Complex((r * b.r + i * b.i) / (b.r * b.r + b.i * b.i), (i * b.r - r * b.i) / (b.r * b.r + b.i * b.i));
}
};
int R[int(1e6 + 10000)];
Complex x[int(1e6 + 10000)], y[int(1e6 + 10000)];
void get_R(int lim) {
for (int i = 0; i < lim; i++) {
R[i] = (i & 1) * (lim >> 1) + (R[i >> 1] >> 1);
}
}
void FFT(Complex *f, int lim, int rev) {
for (int i = 0; i < lim; i++) {
if (i < R[i]) swap(f[i], f[R[i]]);
}
for (int mid = 1; mid < lim; mid <<= 1) {
Complex wn = Complex(cos(pi / mid), rev * sin(pi / mid));
for (int len = mid << 1, cur = 0; cur < lim; cur += len) {
Complex w = Complex(1, 0);
for (int k = 0; k < mid; k++, w = w * wn) {
Complex x = f[cur + k], y = w * f[cur + mid + k];
f[cur + k] = x + y, f[cur + mid + k] = x - y;
}
}
}
if (rev == -1) {
for (int i = 0; i < lim; i++) {
f[i].r /= lim;
}
}
}
ll quick_pow(ll ans, ll p, ll res = 1) {
for(; p; p >>= 1, ans = ans * ans % mod)
if(p & 1) res = res * ans % mod;
return res % mod;
}
ll ans[200010];
inline void solve() {
int n, X; cin >> n >> X;
rep(i, 1, n) {
int xx; cin >> xx;
ans[i] = ans[i - 1] + (xx < X);
x[ans[i]].r ++;
y[200000 - ans[i]].r ++;
x[i].i = y[i].i = 0;
}
x[0].r ++, y[200000].r ++;
int lim = 1; while (lim <= 400000) lim <<= 1;
get_R(lim);
FFT(x, lim, 1);
FFT(y, lim, 1);
rep(i, 0, lim - 1) x[i] = x[i] * y[i];
FFT(x, lim, -1);
cout << (ll(x[200000].r + 0.5) - n - 1) / 2;
rep(i, 1, n) cout << ' ' << ll(x[200000 + i].r + 0.5);
cout << '\n';
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
// freopen("output", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}