I’m new to working on segtrees and i needed to solve a problem where i find the first value > x
in a certain range.
I’ve been using the recursive method to create the segtree and to update it, but i wasn’t able to retrieve the index of the first value > x
in my range.
I’ll paste all of my code here in case it can help:
//THIS IS THE GRADER, IGNORE UNTIL THE SOLUTION PART -------------------------------------
#include <utility>
#include <iostream>
#include <vector>
using namespace std;
// Declaring variables
static int R;
static vector<int> risultato1;
static vector<int> risultato2;
// Declaring functions
void inizializza(int N, vector<int> H);
// Functions ad-hoc for this grader
pair<int, int> chiedi(int x);
void cambia(int x, int h);
void leggi_eventi(int M) {
for (int i = 0; i < M; i++) {
char tipo;
cin >> tipo;
if (tipo == 'Q') {
int x;
cin >> x;
pair<int, int> risultato = chiedi(x);
risultato1[R] = risultato.first;
risultato2[R] = risultato.second;
R++;
} else {
int x, h;
cin >> x >> h;
cambia(x, h);
}
}
}
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
// Reading input
int N, M;
cin >> N >> M;
vector<int> H(N);
risultato1.resize(M);
risultato2.resize(M);
for (int i = 0; i < N; i++) {
cin >> H[i];
}
// Calling functions
inizializza(N, H);
leggi_eventi(M);
// Writing output
for (int i = 0; i < R; i++) {
cout << risultato1[i] << ' ' << risultato2[i] << 'n';
}
return 0;
}
//SOLUTION-------------------------------------------------------------------------------
//SEGMENT TREE
vector<int> seg;
vector<int> torre;
int sizeN;
//recursive build of the segtree
long long int build(int i, int l, int r, vector<int> &torri) {
if(r-l==1) return seg[i] = torri[l]; //base case
int mid = (l+r)/2; //split in half
seg[i] = max(build(2*i, l, mid, torri), build((2*i)+1, mid, r, torri));
//return the value of the segment
return seg[i];
}
//recursive update of the segtree
void update(int i, int l, int r, int pos, long long int val) {
if(r-l==1) { seg[i] = val; return; } //base case
int mid = (l+r)/2; //find the middle
if(pos<mid) update(2*i, l, mid, pos, val); //left half
else update(2*i+1, mid, r, pos, val); //right half
seg[i] = max(seg[2*i],seg[2*i+1]); //update with the max
}
int query_destra (int i, int l, int r, int ql, int qr, int x) {
//base case
if (ql >= r or qr <= l) return -1;//no intersection
if (l >= ql and r <= qr) { //included
if(seg[i] <= x) return -1; //if ... the node is not interesting
//return i; <----------- IM MISSING SOMETHING HERE TO MAKE IT RETURN I CORRECTLY
}
int mid = (l+r)/2; //find the center
//prioritizes the first value, if its not interesting, go to the second
int ans = query_destra(2*i, l, mid, ql, qr, x);
if(ans != -1) return ans;
return query_destra(2*i+1, mid, r, ql, qr, x);
}
pair<int, int> chiedi(int x) {
return make_pair(0 /*query_sinistra(1,0,sizeN, 0, x, torre[x])*/,query_destra(1, 0, sizeN, x, sizeN, torre[x]));
}
void cambia(int x, int h) {
update(1, 0, sizeN, x, h);
}
void inizializza(int N, vector<int> H) {
sizeN = H.size();
torre.resize(sizeN);
seg.resize(sizeN*4);
for(int i=0; i<sizeN; i++) torre[i] = H[i];
build(1,0,N,H);
}
I’ve been able to retrieve the highest in the range, but not the first, so i tried a different approach: I tried simply putting “return i
” inside the included cases but from the results it gave me it was VERY wrong, and not putting somewhere “return i
” simply makes it return -1 each time.
After failing on my own, i tried following what other people did, but not only i wasn’t able to understand most of the code they used, but it also didn’t work for what I needed to do.
An example of how the result should be, with a starting array of [6, 4, 2, 0, 8, 4]
, with x = 4
and my range going from position 1 to position 5, my program should be able to return 4 (the position of the 8, the first number higher than the starting one).
I have to do this thing for a number in the array both forwards and backwards.
Any help is appreciated, thanks in advance.
Tizio is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.