注意到两点:
1.n个节点的完全K叉树中,有儿子的节点数量是O(n/k).而Hn是O(nlogn)的.
2.每个节点的儿子是一段连续的区间,因此我们就可以用可持久化线段树来高效查找.
/* I will wait for you*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <string>
#define make make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int maxn = 300010;
const int maxm = 1010;
const int maxs = 26;
const int inf = 0x3f3f3f3f;
const int P = 1000000007;
const double error = 1e-9;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch <= 47 || ch >= 58)
f = (ch == 45 ? -1 : 1), ch = getchar();
while (ch >= 48 && ch <= 57)
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
struct node
{
int l, r, size;
node *ls, *rs;
node(int a, int b) {
l = a, r = b, size = 0;
ls = rs = 0;
}
} *su[maxn];
int n, u, v, ans[maxn], num[maxn], w[maxn];
map<int, int> now;
node* perbuild(int l, int r)
{
node* o = new node(l, r);
if (l == r)
return o;
int mid = (l + r) / 2;
o -> ls = perbuild(l, mid);
o -> rs = perbuild(mid + 1, r);
return o;
}
node* insert(node* p, int w)
{
int l = p -> l, r = p -> r;
node *o = new node(l, r);
o -> size = p -> size + 1;
o -> ls = p -> ls, o -> rs = p -> rs;
if (l == r)
return o;
int mid = (l + r) / 2;
if (w <= mid)
o -> ls = insert(p -> ls, w);
if (w > mid)
o -> rs = insert(p -> rs, w);
return o;
}
int query(node *a, node *b)
{
int l = a -> l, r = b -> r;
if (l >= u && r <= v)
return b -> size - a -> size;
int mid = (l + r) / 2, ans = 0;
if (u <= mid)
ans += query(a -> ls, b -> ls);
if (v > mid)
ans += query(a -> rs, b -> rs);
return ans;
}
int main()
{
n = read();
su[0] = perbuild(1, n);
for (int i = 1; i <= n; i++)
w[i] = num[i] = read();
sort(w + 1, w + 1 + n);
for (int i = 1; i <= n; i++)
now[w[i]] = i;
for (int i = 1; i <= n; i++) {
num[i] = now[num[i]];
su[i] = insert(su[i - 1], num[i]);
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= n; j++) {
int l = i * (j - 1) + 2;
int r = i * j + 1;
if (l > n)
break;
if (r > n)
r = n;
if (num[j] == 1)
continue;
u = 1, v = num[j] - 1;
ans[i] += query(su[l - 1], su[r]);
}
printf("%d ", ans[i]);
}
return 0;
}