Luckyleaves's Blog

stay hungry,stay foolish greedy and lucky

CF1659D

先鸽了,补完了。

有$O(n)$的做法,不会,就写$n \log n$的。

Solution

首先我们考虑从最后一位开始,逐步确定整个序列。

为什么这么做呢,主要是因为发现将前面所有数字加起来除以$n$就是这个序列中一的个数,同时,我们看一下最后一位的大小是否大于$n-1$就可以判断最后一位是否存在$1$,然后就可以将最后一次排序的贡献从最后一次排序中删除,依次向前计算即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include<bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
template <class T>
inline void read(T &res)
{
res = 0; bool flag = 0;
char c = getchar();
while('0' > c || c > '9') { if(c == '-') flag = 1; c = getchar();}
while('0' <= c && c <= '9') res = (res << 3) + (res << 1) + (c ^ 48), c = getchar();
if(flag) res = -res;
}
template <class T, class ...Arg>
inline void read(T &res, Arg &...com){ read(res), read(com...);}
template <class T>
void out(T res)
{
if(res > 9) out(res / 10);
putchar(res % 10 + '0');
}
template <class T>
inline void write(T res)
{
if(res < 0) putchar('-'), res = -res;
out(res);
}
const int N = 2e5 + 5;
int n, T, k;
int a[N];
struct Node{
#define l(x) (x << 1)
#define r(x) (x << 1 | 1)
int l, r, v, flag;
}tr[N << 2];
inline void pushup(int x)
{
tr[x].v = tr[l(x)].v + tr[r(x)].v;
}
inline void change(int x, int flag)
{
tr[x].v += (tr[x].r - tr[x].l + 1) * flag;
tr[x].flag += flag;
}
inline void pushdown(int x)
{
if(!tr[x].flag) return ;
change(l(x), tr[x].flag);
change(r(x), tr[x].flag);
tr[x].flag = 0;
}
void build(int x, int l, int r)
{
tr[x] = {l, r, 0, 0};
if(l == r) return tr[x].v = a[l], void();
int mid = l + r >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
pushup(x);
}
void modify(int x, int l, int r, int v)
{
if(l <= tr[x].l && tr[x].r <= r) return change(x, v);
pushdown(x);
int mid = tr[x].l + tr[x].r >> 1;
if(l <= mid) modify(x << 1, l, r, v);
if(mid < r) modify(x << 1 | 1, l, r, v);
pushup(x);
}
int query(int x, int l, int r)
{
if(l <= tr[x].l && tr[x].r <= r) return tr[x].v;
pushdown(x);
int mid = tr[x].l + tr[x].r >> 1, res = 0;
if(l <= mid) res += query(x << 1, l, r);
if(r > mid) res += query(x << 1 | 1, l, r);
return res;
}
int ans[N];
signed main()
{
read(T);
while(T --)
{
read(n);
for(int i = 1;i <= n;i ++) read(a[i]);
build(1, 1, n);
for(int i = n, res = 0;i >= 1;i --)
{
res = query(1, 1, i) / i;
if(i == 1)
{
ans[i] = res;
break;
}
if(res) modify(1, i - res + 1, i, -1);
ans[i] = query(1, i, i) / (i - 1);
}
for(int i = 1;i <= n;i ++) write(ans[i]), putchar(' ');
puts("");
}
return 0;
}