2019杭电多校第三场1007 HDU-6609 Find the answer
题意:从第一项到第i项的前缀和,如果大于K,问最少删除多少个[1,i]区间内的元素才能小于等于K。因为一共有N个数,所以有N个前缀和,要输出N个值。
PS:最后一个数后面也有空格,这个真的过分。
题解: 建一颗空的[1,n]线段树(用来维护当前值的个数和总和(sum))。因为第一个数一定符合(a[1]<=K),所以直接输出第一个0,然后把第一个值加进来,单点修改线段树的叶子节点(即:把那个值加入线段树中)。然后第二个值(a[2])先不加入,判断线段树中有多少个尽可能多的值的和能小于等于(K-a[2]),然后将这些小的值的个数减去,就能得到最后需要删除的数的个数。
PS2:线段树中的值是经过离散化再除去重复后再排序的,存在vector < ll > v中,因为数据量太大了,必须离散化。不过到了9102年还有题目这样卡空间,真是惊了我
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<math.h>
#include<vector>
typedef long long ll;
using namespace std;
const int MAX = 2e5+7;
vector < ll>v;
struct node
{
int l, r;
ll sum;
ll num;
}tree[MAX*19];
void build(int id, int l, int r) {
tree[id].l = l;
tree[id].r = r;
tree[id].sum = 0;
tree[id].num = 0;
int mid = (l + r) / 2;
if (l == r)
return ;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
void push_up(int id) {
tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num;
tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum;
}
void update(int id, int pos) {
int l = tree[id].l, r = tree[id].r;
if (l == r) {
tree[id].num++;
tree[id].sum += v[tree[id].l - 1];
}
else {
int mid = (l + r) / 2;
if (pos > mid) update(id << 1 | 1, pos);
else update(id << 1, pos);
push_up(id);
}
}
int query(int id, int s) {
if (s >= tree[id].sum){
return tree[id].num;
}
else if (tree[id].l == tree[id].r) {
return s / v[tree[id].l - 1];
}
if (tree[id << 1].sum >= s) return query(id << 1, s); //因为经过排序
//左子树会保存小一些的数值,所以先遍历左子树
else return tree[id << 1].num + query(id << 1 | 1, s- tree[id<<1].sum);
}
int getid(int x) { //std的map太慢了,手写一个
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
ll a[MAX];
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
v.push_back(a[i]);
}
sort(v.begin(), v.end()); //离散化
v.erase(unique(v.begin(), v.end()), v.end()); //离散化去重复
build(1, 1, v.size());
printf("0 ");
update(1, getid(a[1]));
for (int i = 2; i <= n; i++) {
int re = i - query(1, k - a[i]) - 1;
printf("%d ", re);
update(1, getid(a[i]));
}
printf("\n");
}
return 0;
}