1

Тема: Timus 1019

http://acm.timus.ru/problem.aspx?space=1&num=1019

Интересует решение с помощью дерева отрезков;

Вот что-то я не очень понимаю, что именно нужно в нем хранить.  Пытался хранить координату начала и длину самого длинного белого кусочка в поддереве, а также длину белых кусочков, примыкающих к краям отрезка, соответствующего , но не пошло. need help одним словом. Не откажусь от кода, только желательно понятного, лучше всего с какими-нибудь комментами.

2

Re: Timus 1019

Почему бы просто не хранить картинку? Всего 10000 различных координат, поэтому их можно ужать сначала, и потом хранить для каждой точки её цвет.

3 Отредактировано 2rf (2009-08-20 19:51:50)

Re: Timus 1019

Т. е. вы имеете в виду просто красить отрезки, а потом пробежаться по ним и найти самый длинный из них? Блин, почему мне эта идея в голову не пришла sad , спасибо.

Но если у нас есть запросы вида перекраска отрезка и какой самый длинный белый отрезок сейчас, то Ваша идея видимо не катит, т. к. второй запрос за O(n). Хотелось бы оба запроса уметь за O(log n).

4

Re: Timus 1019

возьмите все концы всех отрезков и отсортируйте. эти точки разделят отрезок (0,10^9) на какое-то кол-во отрезков. чтобы найти цвет отрезка просто берете его середину и перебирая все перекрашивания находите. итого все это будет работать за O(N^2).

5

Re: Timus 1019

да да да, это всё прекрасно, но мне нужно решение за O(n log n)!

Предыдущая идея работала за O(log n) перекраска + O(n) запрос, и т. к. в этой задаче запрос всего 1, то все отлично, НО: интересно, чтобы и то, и то было за O(log n)

6

Re: Timus 1019

Ну во первых,в данной задаче можно писать за квадрат не мучать себя.

Ну а если тебе нужен хороший алгоритм то используй дерево отрезков,где просто будешь находить что именно ты перекрашиваешь и перекрашивать за log(n), так же можно будет как-нибудь находить, это просто нужно придумать.

А если время нужно быстрое,и писать время не очень много,то есть альтернатива,которая хорошо будет работать даже при (N <= 100000), просто разобьём всю плоскость на SQRT(N) отрезков, тогда что получается,что бы перекрасить нам нужно максимум SQRT(N) операций,то есть просто пробежаться и покрасить нужные,а ответ на запрос тоже будет за SQRT(N), так как ты тем же пробегом можешь узнать самый длинный на текущий момент,так же для хорошего ускорения можно в процессе объединять отрезки одинакового цвета,что бы цвета чередовались,
и того Memory: O(N), Time: ~O(N * SQRT(N)).

7

Re: Timus 1019

Ладно, всем спасибо, решил за log n на каждый запрос; оказалось нужно еще хранить в каждой вершине дерева отрезков её цвет, если он известен и одинаков на всем подотрезке, тогда при перекраске нужно просто проталкивать это значение своим детям, если мы из вершины идем вниз.

Непонятно наверное объяснил, но лучше не смогу:)

8

Re: Timus 1019

За NlogN можно без всяких деревьев, встроенными в C++ структурами.
Путь каждая точка конца отрезка это состояние. Будем там хранить начало это или конец, цвет и уровень.
Уровень это порядок в котором отрезки кладутся. Виден отрезок с наибольшим уровнем.
Тогда перебирая все точки в порядке возрастания будем поддерживать set<уровней> из которого будем делать выводы какой отрезок виден.

Код:

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <set> 

using namespace std;

#define Size(x) (int)(x).size()
#define For(i,a,b) for(int i=(int)(a);i<=(int)(b);++i)
#define RepV(i,v) for (int i=0;i<Size(v);++i)

struct state{
    int x, level;
    char start, color;
    state(int x, int level, char start, char color):x(x),level(level),start(start),color(color){}
};

bool by_x(state& a, state& b){
    if (a.x!=b.x) return a.x < b.x;
    if (a.start != b.start) return a.start < b.start;
    return a.level < b.level;
}

int main(){
    vector<state> states;
    states.push_back(state(0,0,1,'w'));
    states.push_back(state(1000000000,0,0,'w'));
    int n;
    scanf("%d",&n);
    For(i,1,n){
        int a, b;
        char c;
        scanf("%d%d %c\n",&a,&b,&c);
        states.push_back(state(a,i,1,c));
        states.push_back(state(b,i,0,c));
    }

    sort(states.begin(),states.end(),by_x);

    vector<pair<int,int> >wlist;
    set<int> w, b;
    RepV(i,states){
        state cur = states[i];
        char color='b';
        if (Size(b)==0 || ( Size(w)>0 && *b.rbegin() < *w.rbegin())){
            color='w';
        }
        if (color=='w'){
            if (i>0)
                wlist.push_back(make_pair(states[i-1].x,cur.x));
        }
        if (!cur.start)
            if (cur.color=='w') w.erase(w.find(cur.level));
            else b.erase(b.find(cur.level));
        else
            if (cur.color=='w') w.insert(cur.level);
            else b.insert(cur.level);
    }

    int len = 0, left = 0;

    int l=-1,r=-1;
    RepV(i,wlist){
        if (wlist[i].first == r) {
            r = wlist[i].second;
        } else {
            if (r-l > len){
                len = r-l;
                left=l;
            }
            l=wlist[i].first;
            r=wlist[i].second;
        }
    }

    if (r-l > len){
        len = r-l;
        left=l;
    }
    printf("%d %d",left,left + len);

    return 0;
}

9

Re: Timus 1019

Но ты на запрос отвечаешь не за log(n), а выше я предложил как это сделать быстрее,
я думаю тут множество способов.

10

Re: Timus 1019

Если последний пост был обращен ко мне, то действительно, запрос получается не за log, а за константу smile

11

Re: Timus 1019

и таму и таму big_smile
я про себя говорил про точный ответ на запрос )