一道很好的线段树+multiset题目,题目中的给的两个算法分别用线段树和multiset处理。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6;
int a[N];
map<int, int> mp;
struct Node{
int l, r, maxn;
}node[N << 2];
int n, c;
typedef long long ll;
void pushup(int root){
node[root].maxn = max(node[root << 1].maxn, node[root << 1 | 1].maxn);
}
void build(int root, int l, int r){
node[root].l = l;
node[root].r = r;
if(l == r){
node[root].maxn = c;
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
pushup(root);
}
void change(int root, int l, int r, int value){
if(node[root].l == node[root].r){
node[root].maxn -= value;
return;
}
if(node[root << 1].maxn >= value)
change(root << 1, l, r, value);
else
change(root << 1 | 1, l, r, value);
pushup(root);
}
int query(int root, int l, int r, int value){
if(node[root].l == node[root].r){
return node[root].l;
}
if(node[root << 1].maxn >= value)
return query(root << 1, l, r, value);
else
return query(root << 1 | 1, l, r, value);
}
int main(){
int t;
scanf("%d", &t);
while(t --){
int ans1, ans2;
multiset<ll> mul;
scanf("%d%d", &n, &c);
build(1, 1, n + 20);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
if(node[1].maxn >= a[i])
change(1, 1, n, a[i]);
}
if(node[node[1].l].maxn < c)
printf("%d ", n);
else{
int pos = query(1, 1, n, c);
printf("%d ", pos - node[1].l);
}
ans2 = 1;
mul.insert(c);
for(int i = 1; i <= n; i ++){
if(*mul.rbegin() < a[i]){
ans2 ++;
mul.insert(c - a[i]);
}else{
multiset<ll>::iterator it = mul.lower_bound(a[i]);
ll num = *it;
mul.erase(it);
mul.insert(num - a[i]);
}
}
printf("%d
", ans2);
}
return 0;
}