小路绫只会做料理 (ayaya)
时间限制: 2 Sec 内存限制: 1024 MB
题目描述
小路绫 (Komichi Aya) 想要给阳子 (Inokuma Youko) 做便当。
小路绫现在有 n n n种食材,编号从 1 1 1到 n n n,她会按编号顺序放入这 n n n种食材。
对于每种食材阳子有一个美味度 a i a_i ai。
小路绫知道,对于所有
1
⩽
i
⩽
n
1 \leqslant i \leqslant n
1⩽i⩽n,设前i种食材的美味度总和
s
i
=
∑
j
=
1
i
a
j
s_{i} = \sum_{j=1}^{i} a_{j}
si=j=1∑iaj
当加入第 i i i种食材时,如果 s i > m s_i>m si>m,阳子就会吃撑。
所以小路绫每放入一种食材时,都会想知道:最少要从之前已经选过的食材中去掉多少食材,才不会让阳子吃撑。
当然,小路绫不会真正地把食材去掉,她只是想知道结果而已。才不是关心你呢!
输入
第一行为两个正整数 n , m n,m n,m,分别表示食材的种类数以及会使阳子吃撑的值 m m m。
接下来为一行 n n n个正整数,其中第i个正整数表示 a i a_i ai。
输出
输出一行 n n n个非负整数,其中第 i i i个非负整数表示在加入第 i i i种食材时,至少要去掉之前加入的多少种食材才能不让阳子吃撑。
样例输入
【样例1】
7 15
1 2 3 4 5 6 7
【样例2】
5 100
80 40 40 40 60
样例输出
【样例1】
0 0 0 0 0 2 3
【样例2】
0 1 1 2 3
提示
对于 100 % 100\% 100%的数据 1 ⩽ n ⩽ 1 0 6 1 ⩽ m ⩽ 1 0 9 1 ⩽ a i ⩽ m 1 \leqslant n \leqslant 10^{6} \quad 1 \leqslant m \leqslant 10^{9} \quad 1 \leqslant a_{i} \leqslant m 1⩽n⩽1061⩽m⩽1091⩽ai⩽m
解体思路
最简单的思路应该是添加
i
i
i时,在
i
−
1
i-1
i−1挑出最大的几个数使得前缀和
s
i
<
=
m
s_i<=m
si<=m
先离散化,用树状数组维护
c
k
表
示
在
c_{k}表示在
ck表示在
1
1
1到
i
−
1
i-1
i−1中前
k
k
k小的和,最后用二分查找最大的k使得
c
k
+
a
[
i
]
⩽
m
c_k+a[i] \leqslant m
ck+a[i]⩽m,统计
1
1
1到
k
k
k中有多少个数就行了,最后的答案就是
i
−
1
−
n
u
m
i-1-num
i−1−num(num表示
1
1
1到
k
k
k中有多少个数)。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
struct node {
int i, v, p;
}a[maxn+10];
bool cmp1(const node &a,const node &b) {
return a.v < b.v;
}
bool cmp2(const node &a,const node &b) {
return a.i < b.i;
}
struct BIT{
ll c[maxn+10],b[maxn+10];
void add(int x,int k) {
for (int i = x; i <= maxn; i += i & -i) {
c[i] += k;
b[i]++;
}
}
ll ask1(int x) {
ll res = 0;
for (int i = x; i; i -= i & -i) {
res += c[i];
}
return res;
}
ll ask2(int x) {
ll res = 0;
for (int i = x; i >= 1; i -= i & -i) {
res += b[i];
}
return res;
}
}B;
int n,m;
void work(int i) {
int l = 1, r = n;
int res = 0;
while (l <= r) {
int mid = l + r >> 1;
if (B.ask1(mid) + a[i].v <= m) {
res = mid;
l = mid + 1;
} else r = mid - 1;
}
printf("%d", i - B.ask2(res) - 1);
}
void Work() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i].v);
a[i].i = i;
}
sort(a + 1, a + 1 + n, cmp1);
for (int i = 1; i <= n; i++) {
a[i].p = i;
}
sort(a + 1, a + 1 + n, cmp2);
for (int i = 1; i <= n; i++) {
work(i);
if (i == n) putchar('\n'); else putchar(' ');
B.add(a[i].p, a[i].v);
}
}
int main() {
Work();
return 0;
}