dopo aver passato svariate ore su questo problema sono finalmente riuscito a risolvere l’esempio di questo problema, ma andando avanti coi test trovo principalmente errori di tempo (execution timed out) e qualche “incorrect output” nelle subtask 4, 5 e 6. Si purtroppo è tanta roba, infatti il risultato è 0/100, e per questo mi servirebbe una grande mano.
#include <vector>
#include <limits>
#include <climits>
using namespace std;
struct Node{
long long val_sum;
long long val_min;
long long left;
long long lazy_add;
long long lazy_set;
int set_last;
Node() : val_sum(0), val_min(LLONG_MAX), left(LLONG_MAX), lazy_add(0), lazy_set(LLONG_MIN), set_last(0) {};
void join(const Node &l, const Node &r){
val_min = min(l.val_min, r.val_min);
val_sum = l.val_sum + r.val_sum;
left = l.left;
}
};
int n, real_size;
vector<Node> nodes;
void build(int u, int l, int r, vector<long long> a){
if(r - l == 1){
if(l < a.size()){
nodes[u].val_sum = a[l];
nodes[u].val_min = a[l];
nodes[u].left = a[l];
}
}
else{
build(2*u, l, (l+r)/2, a);
build(2*u+1, (l+r)/2, r, a);
nodes[u].join(nodes[2*u],nodes[2*u+1]);
}
}
void init(vector<long long> a) {
n = a.size();
real_size = 1;
while(real_size < n)
real_size *= 2;
nodes.assign(2*real_size, Node());
build(1, 0, real_size, a);
}
void checkLazy(int u, int l, int r){
if(nodes[u].lazy_add != 0 && nodes[u].lazy_set != LLONG_MIN){
if(nodes[u].set_last){
nodes[u].val_sum = (r - l) * nodes[u].lazy_set;
nodes[u].val_min = nodes[u].lazy_set;
nodes[u].left = nodes[u].lazy_set;
if(r - l != 1){
nodes[u*2].lazy_set = nodes[u].lazy_set;
nodes[u*2+1].lazy_set = nodes[u].lazy_set;
nodes[u*2].lazy_add = 0;
nodes[u*2+1].lazy_add = 0;
nodes[u*2].set_last = nodes[u].set_last;
nodes[u*2+1].set_last = nodes[u].set_last;
}
}
else{
nodes[u].val_sum = (r - l) * (nodes[u].lazy_set + nodes[u].lazy_add);
nodes[u].val_min = nodes[u].lazy_set + nodes[u].lazy_add;
nodes[u].left = nodes[u].lazy_set + nodes[u].lazy_add;
if(r - l != 1){
nodes[u*2].lazy_set = nodes[u].lazy_set;
nodes[u*2+1].lazy_set = nodes[u].lazy_set;
nodes[u*2].lazy_add = nodes[u].lazy_add;
nodes[u*2+1].lazy_add = nodes[u].lazy_add;
nodes[u*2].set_last = nodes[u].set_last;
nodes[u*2+1].set_last = nodes[u].set_last;
}
}
nodes[u].lazy_set = LLONG_MIN;
nodes[u].lazy_add = 0;
nodes[u].set_last = 0;
}
else{
if(nodes[u].lazy_add != 0){
nodes[u].val_sum += (r - l) * nodes[u].lazy_add;
nodes[u].val_min += nodes[u].lazy_add;
nodes[u].left += nodes[u].lazy_add;
if(r - l != 1){
nodes[u*2].lazy_add += nodes[u].lazy_add;
nodes[u*2+1].lazy_add += nodes[u].lazy_add;
}
nodes[u].lazy_add = 0;
}
if(nodes[u].lazy_set != LLONG_MIN){
nodes[u].val_sum = (r - l) * nodes[u].lazy_set;
nodes[u].val_min = nodes[u].lazy_set;
nodes[u].left = nodes[u].lazy_set;
if(r - l != 1){
nodes[u*2].lazy_set = nodes[u].lazy_set;
nodes[u*2+1].lazy_set = nodes[u].lazy_set;
nodes[u*2].lazy_add = 0;
nodes[u*2+1].lazy_add = 0;
}
nodes[u].lazy_set = LLONG_MIN;
}
}
}
long long get_sum(int u, int l, int r, int x, int y){
checkLazy(u, l, r);
if(x >= r || y <= l) return 0;
if(l >= x && r <= y) return nodes[u].val_sum;
return get_sum(2*u, l, (l+r)/2, x, y) + get_sum(2*u+1, (l+r)/2, r, x, y);
}
long long get_sum(int l, int r) {
return get_sum(1, 0, real_size, l, r);
}
void add(int u, int l, int r, int x, int y, long long val){
checkLazy(u, l, r);
if(x >= r || y <= l) return;
if(l >= x && r <= y){
nodes[u].val_sum += (r - l) * val;
nodes[u].val_min += val;
nodes[u].left += val;
if(r - l != 1){
nodes[2*u].lazy_add += val;
nodes[2*u+1].lazy_add += val;
}
return;
}
add(2*u, l, (l+r)/2, x, y, val);
add(2*u+1, (l+r)/2, r, x, y, val);
nodes[u].join(nodes[2*u],nodes[2*u+1]);
}
void add(int l, int r, long long x) {
add(1,0, real_size, l, r, x);
}
void set_range(int u, int l, int r, int x, int y, long long val){
checkLazy(u, l, r);
if(x >= r || y <= l) return;
if(l >= x && r <= y){
nodes[u].val_sum = (r - l) * val;
nodes[u].val_min = val;
nodes[u].left = val;
if(r - l != 1){
nodes[2*u].lazy_set = val;
nodes[2*u+1].lazy_set = val;
nodes[2*u].set_last = 1;
nodes[2*u+1].set_last = 1;
}
return;
}
set_range(2*u, l, (l+r)/2, x, y, val);
set_range(2*u+1, (l+r)/2, r, x, y, val);
nodes[u].join(nodes[2*u],nodes[2*u+1]);
}
void set_range(int l, int r, long long x) {
set_range(1,0, real_size, l, r, x);
}
long long get_min(int u, int l, int r, int x, int y){
checkLazy(u, l, r);
if(x >= r || y <= l) return LLONG_MAX;
if(l >= x && r <= y) return nodes[u].val_min;
return min(
get_min(2*u, l, (l+r)/2, x, y),
get_min(2*u+1, (l+r)/2, r, x, y)
);
}
long long get_min(int l, int r) {
return get_min(1, 0, real_size, l, r);
}
int lower_bound(int u, int l, int r, int x, int y, long long lim){
if(x >= r || y <= l) return -1;
if(l >= x && r <= y) return nodes[u].left < lim ? u : -1;
int res_left = lower_bound(2*u, l, (l+r)/2, x, y, lim);
if(res_left != -1)
return res_left;
int res_right = lower_bound(2*u+1, (l+r)/2, r, x, y, lim);
return res_right;
}
int lower_bound(int l, int r, long long x) {
int res = lower_bound(1, 0, real_size, l, r, x);
if(res == -1) return -1;
while(res <= real_size) res*=2;
return res - real_size;
}