Witam, mam problem z zadaniem "Zdjęcia" z OIG http://main.edu.pl/pl/archive/oig/2/zdj
Przeczytałem na innych forach że trzeba to zrobić stosując jedno drzewo przedziałowe, sortując wcześniej krawędzie poziome albo pionowe
następnie lecieć po kolejnych krawędziach - jak krawędź dolna to dodajemy jeden na drzewie do elementów w przedziałach <x1, x2> natomiast jak jest górna to odejmuję. Problem polega na tym, iż znaleziona przeze mnie metoda na forum posiana jest w złożoności (n*logn) a ja mam większą złożoność ponieważ zwiększam i zmniejszam przedziały o 1 w taki sposób że opisałem jakie węzły są aktywne (przechowywują aktualne inf o ilości nachodzących zdjęć, no i odpowiednio od sytuacji idę w głąb drzewa albo opisuję wcześniejszy węzeł jako aktywny). Moja złożoność jest na pewno większa od tej jaka jest wymagana (przy czterech ostatnich testach przekraczam czas). Bardzo proszę o pomoc.
Link do forum: http://main.edu.pl/pl/user.phtml?op=forum&page=viewtopic&id=131
Oto mój kod
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
#define gora true
#define dol false
int mm = 0; // max grubość
struct krawedz
{
int y;
int x1;
int x2;
bool poz;
};
// struktura drzewa
struct drz
{
int pocz;
int kon;
int w;
bool czy_ak;
drz()
{
w = 0;
czy_ak = false;
pocz = -1;
kon = -1;
}
};
drz *drzewo = new drz[1048576];
bool funkcja_porownywujaca(krawedz A, krawedz B)
{
if (B.y > A.y)
return true;
if (A.y > B.y)
return false;
if (A.poz == dol && B.poz == gora)
return true;
return false;
}
// funkcja jaką zwiększam albo zmniejszam wartości w węzłach
void dodaj(int x1, int x2, int g, bool uzu)
{
// sprawdam czy drzewo ma węzeł akrywny i czy cały przedział węzła ma być zwiększony
if (drzewo[g].pocz >= x1 && drzewo[g].kon <= x2 && drzewo[g].czy_ak == true)
{
if (uzu == false)
{
drzewo[g].w++;
if (drzewo[g].w>mm)
mm = drzewo[g].w;
}
else drzewo[g].w--;
// skracanie drzewa - w sensie że cofam węzeł aktywny
while (true)
{
if (g == 1)break;
if (g % 2 == 1)
{
g /= 2;
if (drzewo[g * 2].w == drzewo[g * 2 + 1].w)
{
drzewo[g].w = drzewo[g * 2].w;
drzewo[g].czy_ak = true;
drzewo[g * 2].czy_ak = false;
drzewo[g * 2 + 1].czy_ak = false;
}
else break;
}
else break;
}
return;
}
// jak przedział zawarty jakkolwiek ale zawarty
else if ((drzewo[g].pocz <= x1 && drzewo[g].kon >= x1)
|| (drzewo[g].pocz <= x2 && drzewo[g].kon >= x2)
|| (x1 <= drzewo[g].pocz && drzewo[g].kon <= x2))
{
// przesunięcie węzła aktywnego w dół
if (drzewo[g].czy_ak == true)
{
drzewo[g * 2].w = drzewo[g].w;
drzewo[g * 2 + 1].w = drzewo[g].w;
drzewo[g * 2].czy_ak = true;
drzewo[g * 2 + 1].czy_ak = true;
drzewo[g].czy_ak = false;
}
dodaj(x1, x2, g * 2, uzu);
dodaj(x1, x2, g * 2 + 1, uzu);
}
}
int main()
{
int n;
cin >> n;
vector <krawedz> kr;
krawedz pom;
// wczytanie krawędzi
for (int a = 0; a < n; a++)
{
cin >> pom.x1 >> pom.y >> pom.x2;
pom.x1 += 200000;
pom.x2 += 200000;
pom.y += 200000;
pom.poz = dol;
kr.push_back(pom);
cin >> pom.y;
pom.y += 200000;
pom.poz = gora;
kr.push_back(pom);
}
// sortowanie krawędzi
sort(kr.begin(), kr.end(), funkcja_porownywujaca);
// drzewo - uzupełnianie początkowe
for (int a = 0; a < 400001; a++)
{
drzewo[524288 + a].pocz = a;
drzewo[524288 + a].kon = a;
}
for (int a = 262144; a >= 1; a /= 2)
for (int b = a; b < a * 2; b++)
{
if (drzewo[2 * b + 1].kon != -1)
{
drzewo[b].pocz = drzewo[2 * b].pocz;
drzewo[b].kon = drzewo[2 * b + 1].kon;
}
else if (drzewo[2 * b].kon != -1)
{
drzewo[b].pocz = drzewo[2 * b].pocz;
drzewo[b].kon = drzewo[2 * b].kon;
}
}
drzewo[1].czy_ak = true;
// dodawanie i odejmowanie kolejnych krawedzi
for (int a = 0; a < kr.size(); a++)
{
dodaj(kr[a].x1, kr[a].x2, 1, kr[a].poz);
}
cout << mm << endl;
system("PAUSE");
return 0;
}