Por Samyra Almeida
Para resolver esse problema é necessário conhecer sobre a estrutura de dados BIT (Binary Indexed Tree ou Árvore de Indexação Binária, em tradução livre) também conhecida como Árvore de Fenwink (Fenwick Tree) e sobre o Algoritmo de Mo (esse tutorial está em inglês).
Bem, essa questão é bem semelhante ao Algoritmo de Mo tradicional (quantas vezes um determinado número aparece em um intervalo de até ), só que como queremos saber quantos prédios são maiores a uma determinada altura , utilizaremos uma BIT de frequência, onde a função atualizará o intervalo até e a consultará quantos prédios existem com a altura de até (maior altura possível que segundo o enunciado da questão é ). Sendo assim ao adicionarmos um prédio ao intervalo iremos fazer e ao removermos um prédio faremos , vale lembrar que no vetor temos a altura de todos os prédios. E para consultar quantos prédios existem com altura maior que iremos fazer , a cada pergunta de Sufia iremos salvar a resposta do intervalo no vetor . Ao final no algoritmo basta imprimirmos o vetor .
Para maior compreensão, segue o código solução:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
const int maxn = 3e6+10, root = 320, maxv = 1e6; | |
int resp, n, q, v[maxn], f[maxn], ans[maxn], bit[maxn]; | |
struct Q | |
{ | |
int l, r, y, id, b; | |
bool operator<(const Q& o) const | |
{ | |
if(b == o.b) // otmização de paridade, não precisa (NESSE CASO) mas não custa nada sempre colocar =) | |
{ | |
if(b&1) return r > o.r; // se o bloco for ímpar, ordenamos do maior r para o menor | |
else return r < o.r; // se for par, ordenamos do menor r para o maior | |
} | |
return b < o.b; // se estivermos em blocos diferente ordenamos do menor para o maior bloco | |
} | |
} qr[maxn]; | |
int query(int p) // responde quantos números maiores que p existem | |
{ | |
int sum = 0; | |
while(p <= maxv && p) | |
{ | |
sum += bit[p]; | |
p += (p & -p); | |
} | |
return sum; | |
} | |
int upd(int p, int val) // atualizo adicono val em p | |
{ | |
while(p > 0) | |
{ | |
bit[p] += val; | |
p -= (p & -p); | |
} | |
} | |
int main() | |
{ | |
cin >> n >> q; | |
for(int i = 1 ; i <= n ; ++i) cin >> v[i]; | |
for(int i = 0 ; i < q ; ++i) | |
{ | |
cin >> qr[i].l >> qr[i].r >> qr[i].y; // leio as perguntas de Sufia | |
qr[i].id = i; | |
qr[i].b = (qr[i].l/root); | |
} | |
// Algoritmo de Mo | |
sort(qr, qr+q); // ordeno as perguntas | |
int left = 0, right = 0; | |
for(int i = 0 ; i < q ; ++i) | |
{ | |
int l = qr[i].l; | |
int r = qr[i].r; | |
int y = qr[i].y; | |
int id = qr[i].id; | |
while(right < r) // a rua right esta no dentre do meu intervalo | |
{ | |
right++; // aumento o intevalo | |
upd(v[right], 1); // adiociono o prédio na bit | |
} | |
while(left > l) // a rua left esta no dentre do meu intervalo | |
{ | |
left--; // aumento o intervallo | |
upd(v[left], 1); // adiciono o prédio na bit | |
} | |
while(right > r) // a rua right não esta no dentre do meu intervalo | |
{ | |
upd(v[right], -1); // removo o prédio na bit | |
right--; // diminuo o intervalo | |
} | |
while(left < l) // a rua left não esta no dentre do meu intervalo | |
{ | |
upd(v[left], -1); // removo o prédio na bit | |
left++; // diminuo o intervalo | |
} | |
ans[id] = query(y+1); // consulto quantos prédio com altura maior que y existem entre as ruas l e r | |
} | |
for(int i = 0 ; i < q ; ++i) // imprimo as respostas | |
{ | |
cout << ans[i] << "\n"; | |
} | |
} |