Кола, що ділять площину


23

Завдання

Вам буде дано набір кіл у площині з їх центрами на прямій y = 0 . Гарантується, що жодна пара кіл не має більше однієї загальної точки.

Ваше завдання - визначити, на скільки областей поділяють площину кола. Область - це максимально суміжний набір точок, що не перетинає жодне з кіл.

Вам слід написати програму, яка обчислює цю відповідь, коли дається опис кіл.


Ось приклад:

приклад 1

З лівого боку ви бачите кола, намальовані в площині. Однак у правій половині зображення регіони, отримані колами, виразно кольорові (один колір на регіон). У цьому прикладі є шість регіонів.


Вхідні дані

Перший рядок введення містить число, Nчисло описів кола, яке слід слідувати. Цей рядок необов’язковий, якщо ваше рішення працює без нього, це добре.

Наступні Nрядки містять два цілих числа, x i та r i > 0 , що представляють коло з центром (x i , 0) та радіусом r i .

Гарантується, що жодна пара кіл не має більше однієї загальної точки. Далі гарантується, що x i і r i не перевищують 10^9абсолютного значення (тому вони зручно вписуються в 32-бітове ціле число).


Вхід може бути:

  • читати з STDIN

  • читати з файлу, названого Iв поточному каталозі

Як варіант, вхід може бути:

  • доступний у вигляді рядка (включаючи нові рядки) у глобальній змінній

  • на стеку


Вихід

Це має бути єдине ціле число, число до отриманих регіонів. Це має бути записано в STDOUT або файл, названий Oу поточному каталозі.


Правила

  • Виграє найкоротший код у байтах

  • +200 байт штрафу, якщо ваш код не має в поліномі часу виконання + складності простору n

  • -100 байт-бонус за найгірший очікуваний час виконання + складність простору O(n log n)

  • -50 байт-бонус за найгірший очікуваний час виконання + складність простору O(n)

  • -100 байт-бонус за детермінований час виконання + складність простору O(n)

Під час оцінки часу виконання:

  • Припустимо, що в хеш-таблицях O(1)очікується час виконання для вставки, видалення та пошуку, незалежно від послідовності операцій та вхідних даних. Це може бути, а може і не бути правдою, залежно від того, чи використовує реалізація рандомізацію.

  • Припустимо, що вбудований вид вашої мови програмування займає детермінований O(n log n)час, де nрозмір послідовності введення.

  • Припустимо, що арифметичні операції над вхідними числами займають лише O(1)час.

  • Не припускайте, що вхідні числа пов'язані постійною, хоча з практичних причин вони є. Це означає, що такі алгоритми, як сортування radix або сортування підрахунку, не є лінійним часом. Загалом слід уникати дуже великих постійних факторів.


Приклади

Вхід:

2 
1 3
5 1

Вихід: 3


Вхід:

3
2 2
1 1
3 1

Вихід: 5

4
7 5
-9 11
11 9
0 20

Вхід:

9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2

Вихід: 11


Підказки

Наступну ідею ми можемо використати для дуже компактного рішення. Дозволяє перетинати набір кіл з віссю X та інтерпретувати точки перетину як вузли на площинному графіку:

введіть тут опис зображення

Кожне коло створює рівно 2 ребра на цьому графіку та до двох вузлів. Ми можемо порахувати кількість вузлів, використовуючи хеш-таблицю, щоб відстежувати загальну кількість чітких лівих чи правих меж.

Тоді ми можемо використовувати характерну формулу Ейлера для обчислення кількості граней малюнка графіка:

V - E + F - C = 1

F = E - V + C + 1

Для обчислення Cкількості підключених компонентів ми можемо скористатися глибинним першим пошуком .


Примітка. Ця ідея проблеми запозичена з недавнього хорватського конкурсу програмування , але, будь ласка, не обманюйте, дивлячись на контури рішення. :)


Деякі з цих бонусів примари?
user2357112 підтримує Моніку

@ user2357112 Не припускайте, що це неможливо зробити, якщо ви не зможете це довести;)
Niklas B.

Ну, маючи входи, гарантовано вміщені в ціле число машини, ми могли б використати сортування radix і назвати його O (n). Я ненавиджу припускати обмежений розмір вводу, тому що, строго кажучи, це означає, що існує безліч можливих входів.
user2357112 підтримує Моніку

@ user2357112 Ні, я сказав, що ви не можете вважати цілі числа обмеженими під час оцінювання асимптотики, тому ні сортування радіації, ні сортування підрахунку не буде лінійним часом та простором. Те, що вони вкладаються в слово, це просто зробити арифметику "справжньою" O (1) і з практичних причин (обмежена змінна ширина в більшості мов)
Ніклас Б.

@NiklasB. якщо у мене є алгоритм, в якому єдиним компонентом із надлінійною складністю є сортування, я повинен здійснити сортування злиття, якщо моя мова використовує швидке сортування, щоб отримати n log nбонус? Крім того, у мене є нове концептуально нове рішення. Чи слід публікувати нову відповідь про заміну старої? (Я вважаю за краще колишнє, якщо моє нове рішення насправді не є правильним)
Мартін Ендер

Відповіді:


2

Математика, 125 122 - 150 = -28 знаків

Я не знаю складності вбудованої функції ConnectedComponents.

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&

Використання:

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&[
"9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2"]

11


Я думаю, ми можемо з упевненістю припустити, що ConnectedComponentsмає лінійну очікувану найгіршу складність, тому, якщо є O (n) компоненти, це було б добре. Я не розумію Mathematica, тому не можу сказати, чи загальна вона (n) і чи відповідає бонус -150? Я думаю, що так і є. Я просто запускаю його з введенням в STDIN?
Ніклас Б.

@NiklasB. його метод введення - це просто передача змінної рядка анонімній функції. тому я вважаю, що це має кваліфікувати. що стосується виводу, то в Mathematica це просто призведе до того, що число вийде на консольний вихід, так що, мабуть, теж буде добре.
Мартін Ендер

Я перевірив правильність цього, тому думаю, що з оцінкою -28 це новий лідер. Вітаємо!
Ніклас Б.

@NiklasB. чому лише 150? Яка частина алгоритму має надлінійну найгіршу складність?
Мартін Ендер

@ m.buettner 150 - це очікуваний час для O (n). Для графіків з довільними числами як вузли, неявно визначені, як тут, ви просто не можете знайти кількість СС у лінійному часі, що може бути показано зменшенням відмінності елементів до підключених компонентів. Я думаю, ми також можемо зменшити виразність елементів до початкової проблеми
Ніклас Б.

4

Рубі - 312 306 285 273 269 259 символів

Ця відповідь була замінена іншим моїм підходом, який використовує значно менше символів і працює O(n log n).

Гаразд, підемо. Для початку я просто хотів робочої реалізації, тому це ще не алгоритмічно оптимізовано. Я сортую кола від найбільшого до найменшого та будую дерево (кола, що входить до інших кіл, є дітьми тих більших). Обидві операції проходять O(n^2)в гіршому і O(n log n)в кращому випадку. Потім я перебираю через дерево, щоб рахувати площі. Якщо діти кола заповнюють весь його діаметр, з’являються дві нові області, інакше є лише одна. Це ітерація O(n). Тож у мене складна загальна складність O(n^2)і претендую ні на винагороду, ні на штраф.

Цей код очікує, що вхід без кількості кіл буде збережений у змінній s:

t=[]
s.lines.map{|x|x,r=x.split.map &:to_i;{d:2*r,l:x-r,c:[]}}.sort_by!{|c|-c[:d]}.map{|c|i=-1;n=t
while o=n[i+=1]
if 0>d=c[:l]-o[:l]
break
elsif o[:d]>d
n=o[:c]
i=-1
end
end
n[i,0]=c}
a=1
t.map &(b=->n{d=0
n[:c].each{|c|d+=c[:d]}.map &b
a+=d==n[:d]?2:1})
p a

Невикористана версія (очікує введення в змінну string):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_i
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius, children:[]}
}
list.sort_by! { |circle| -circle[:d] }
tree = []
list.map { |circle|
  i = -1
  node = tree
  while c=node[i+=1]
    if circle[:x]<c[:l]
      break
    elsif circle[:x]<c[:r]
      node = c[:children]
      i = -1
    end
  end
  node[i,0] = circle
}
areas = 1
tree.map &(count = -> node {
  d = 0
  i = -1
  while c=node[:children][i+=1]
    count.call c
    d += c[:d]
  end
  areas += d == node[:d] ? 2 : 1
})
p areas

@NiklasB. так, тестовий випадок був би непоганим. Відношення, яке визначає краї мого дерева, - це просто включення одного кола в інше. Оскільки коло не може міститись у двох колах, які не містять одне одного (через умови "одного перехрестя"), я не бачу, як це може бути DAG.
Мартін Ендер

Чи онуки вузла також є його дітьми?
user2357112 підтримує Моніку

@ user2357112 ні, тому що вони можуть розділити лише свого прямого батька
Мартіна Ендера

@NiklasB. Якщо я запускаю це з прикладом у вашому запитанні, я отримую 11. Для того, хто у вашому коментарі 9.
Мартін Ендер

@NiklasB. зачекайте, я насправді отримую 10і 8з моєю версією без вольфів, але 11і 9з моєю поточною версією для гольфу: D
Мартін Ендер

2

Рубі, 203 183 173 133 - 100 = 33 символи

Тож тут інший підхід. Цього разу я сортую кола за їх кращою лівою точкою. Кола, що торкаються в самій лівій точці, відсортовані від найбільшого до найменшого. Це вимагає O(n log n)(ну, Ruby використовує швидке сортування, тому насправді, O(n^2)але реалізація сортування злиття / купи, ймовірно, виходить за рамки цього завдання). Потім я повторюю цей список, згадуючи всі найбільш ліві та праві праві позиції гуртків, які я відвідав. Це дозволяє мені виявити, чи ряд кіл з’єднується по всьому протяжному більшому колу. У цьому випадку є дві підрайони, інакше лише одна. Ця ітерація займає лише O(n)надання загальної складності, O(n log n)яка відповідає нагороді 100 символів.

Цей фрагмент очікує, що вхід буде наданий через файл в аргументах командного рядка без кількості кіл:

l,r={},{}
a=1
$<.map{|x|c,q=x.split.map &:to_r;[c-q,-2*q]}.sort.map{|x,y|a+=r[y=x-y]&&l[x]?2:1
l[y]=1 if l[x]&&!r[y]
l[x]=r[y]=1}
p a

Невиконана версія (очікує введення в змінну string):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_r
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius}
}
list.sort_by! { |circle| circle[:l] + 1/circle[:d] }
l,r={},{}
areas = 1
list.map { |circle|
  x,y=circle[:l],circle[:r]
  if l[x] && r[y]
    areas += 2
  else
    areas += 1
    l[y]=1 if l[x]
  end
  r[y]=1
  l[x]=1
}
p areas

На жаль, це не вдається для всіх великих тестів. Хоча це швидко;) На цей раз у мене немає невеликого невдалого прикладу, але ви можете знайти тестові дані на веб-сайті конкурсу, на який я пов’язаний (це конкурс №6)
Ніклас Б.

Перший невдалий тест - kruznice / kruznice.in.2, який є першим "справжнім" тестом, тому я припускаю, що в алгоритмі чи реалізації є щось принципово неправильне. Чи правильно це працює з довільно вкладеними колами?
Ніклас Б.

@NiklasB. дякую, я перегляну тестові справи (можливо, мені доведеться до завтра ввечері, щоб виправити це)
Мартін Ендер

@NiklasB. Я зрозумів, проблема і мінімальний провал приклад вимагає 5 кіл: -1 1 1 1 0 2 4 2 0 6. Я подумаю, як це виправити до завтрашнього вечора (сподіваюся).
Мартін Ендер

Ваш аналіз складності, здається, передбачає, що доступ асоціативного масиву - це постійний час. Це здається малоймовірним у гіршому випадку.
Пітер Тейлор

1

Юлія - ​​260 -100 (бонус?) = 160

Інтерпретуючи кола як фігури з вершинами (перетинами), ребрами та гранями (області площини), ми можемо співвідносити один одного, використовуючи характеристику Ейлера , тому нам потрібно лише знати кількість "вершин" та "ребер", щоб мати число "граней" або областей площини за формулою, записаною нижче:Хайлерова характеристика

ОНОВЛЕННЯ: Поміркувавши деякий час, я зрозумів, що проблема з моїм методом була лише тоді, коли кола, де вони не підключені, тож я прийшов з ідеєю, чому б не штучно їх з'єднати? Тож ціле задовольнить формулу Ейлера.

Приклад кіл

F = 2 + EV (V = 6, E = 9)

[Не працюйте з вкладеними колами, тому це не є відповіддю на проблему для загальних випадків]

Код :

s=readlines(open("s"))
n=int(s[1])
c=zeros(n,2)
t=[]
for i=1:n
    a=int(split(s[i+1]))
    c[i,1]=a[1]-a[2]
    c[i,2]=a[1]+a[2]
    if i==1 t=[c[1]]end
    append!(t,[c[i,1]:.5:c[i,2]])
end
e=0
t=sort(t)
for i in 1:(length(t)-1) e+=t[i+1]-t[i]>=1?1:0end #adds one edge for every gap
2+2n+e-length(unique(c)) # 2+E-V = 2+(2n+e)-#vertices

Я думаю, що ваша програма не зможе 2 -10 1 10 1.
Ніклас Б.

"Гарантується, що жодна пара кіл не має більше однієї загальної точки". тому я думаю, це не застосовуватиметься :)
CCP

@CCP Вони мають нуль загальних точок. n=2, кола є (C=(-10,0), r=1)і(C=(10,0), r=1)
Ніклас Б.

1
Чи не слід підключати графік, щоб застосувати характеристику Ейлера?
user2357112 підтримує Моніку

1
Ах, ось простий випадок: 4 0 2 1 1 10 2 11 1Але я не думаю, що я можу дати вам набагато більше тестових випадків, це було б трохи несправедливо
Ніклас Б.

1

Spidermonkey JS, 308, 287 , 273 - 100 = 173

Я думаю, якби я переписав це на Ruby або Python, я міг би зберегти символів.

Код:

for(a=[d=readline],e={},u=d(n=1);u--;)[r,q]=d().split(' '),l=r-q,r-=-q,e[l]=e[l]||[0,0],e[r]=e[r]||[0,0],e[r][1]++,e[l][0]++
for(k=Object.keys(e).sort(function(a,b)b-a);i=k.pop();a.length&&a.pop()&a.push(0)){for([l,r]=e[i];r--;)n+=a.pop()
for(n+=l;l--;)a.push(l>0)}print(n)

Алгоритм:

n = 1 // this will be the total
e = {x:[numLeftBounds,numRightBounds]} // imagine this as the x axis with a count of zero-crossings
a = [] // this is the stack of circles around the "cursor".  
       // values will be 1 if that circle's never had alone time, else 0
k = sort keys of e on x
for each key in k: // this is the "cursor"
  n += key[numLeftBounds] // each circle that opens has at least one space.
  k[numRightBounds].times {n += a.pop()} // pop the closing circles. if any were never alone, add 1
  k[numLeftBounds].times {a.push(alwaysAlone)} // push the opening circles
  if !a.empty():
     set the innermost circle (top of stack) to false (not never alone)
  fi
loop

Я не дуже великий в нотації O, але я думаю, що це O (n), оскільки я ефективно перебираю кожне коло 3 рази (створюю, ліворуч, праворуч), а також сортую клавіші карти (і сортую для O ( n log n) але це зникає). Це детерміновано?


Якщо хтось має поради, як поєднати rцикл і lцикл в одне твердження, я би вдячний.
Не те, що Чарльз

Ура :) Мені здається, що ваш час виконання справді є O (n log n), завдяки сорту, який був би -100. Я дам вам знати, чи проходить він всі тестові справи.
Ніклас Б.

Приємно, що ваша програма здає всі тестові справи з першої спроби. Я думаю, що щось подібне (точна лінія з деяким станом, що підтримується в стеці) було офіційним рішенням авторів проблеми. Ваша програма отримує загальний бал 173
Ніклас Б.

@NiklasB. Спасибі!
Не те, що Чарльз

Я намагався набагато більш надійне рішення з перекриваючими колами .... тоді я побачив, що вони можуть перетинатися лише в одній точці.
Не те, що Чарльз

-1

JavaScript (ES6) - 255 254 символів - 100 250 Бонус = 155 4

R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Передбачається, що рядок введення знаходиться в змінній Sі виводить кількість регіонів на консоль.

R=/(\S+) (\S+)/ym;                  // Regular expression to find centre and width.
N=1;                                // Number of regions
w=l=0;                              // Maximum width and minimum left boundary.
X=[];                               // A 1-indexed array to contain the circles.
                                    // All the above are O(1)
for(;m=R.exec(S);){                 // For each circle
    X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};
                                    // Create an object with w (width), l (left boundary)
                                    // and r (right boundary) attributes.
    l=k<l?k:l;                      // Update the minimum left boundary.
    w=j<w?w:j                       // Update the maximum width.
}                                   // O(1) per iteration = O(N) total.
M=[];                               // An array.
X.map(x=>M[(x.l-l+1)*w-x.w]=x);     // Map the 1-indexed array of circles (X) to a
                                    // sparse array indexed so that the elements are
                                    // sorted by ascending left boundary then descending
                                    // width.
                                    // If there are N circles then only N elements are
                                    // created in the array and it can be treated as if it
                                    // is a hashmap (associative array) with a built in
                                    // ordering and as per the rules set in the question
                                    // is O(1) per insert so is O(N) total cost.
                                    // Since the array is sparse then it is still O(N)
                                    // total memory.
s=[];                               // An empty stack
i=0;                                // The number of circles on the stack.
M.map(x=>{                          // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

Час складності тепер O (N).

Тестовий випадок 1

S='2\n1 3\n5 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Виходи: 3

Тестовий випадок 2

S='3\n2 2\n1 1\n3 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Виходи: 5

Тестовий випадок 3

S='4\n7 5\n-9 11\n11 9\n0 20';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Виходи: 6

Тестовий випадок 4

S='9\n38 14\n-60 40\n73 19\n0 100\n98 2\n-15 5\n39 15\n-38 62\n94 2';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Виходи: 11

Тестовий випадок 5

S='87\n-730 4\n-836 2\n-889 1\n-913 15\n-883 5\n-908 8\n-507 77\n-922 2\n-786 2\n-782 2\n-762 22\n-776 2\n-781 3\n-913 3\n-830 2\n-756 4\n-970 30\n-755 5\n-494 506\n-854 4\n15 3\n-914 2\n-840 2\n-833 1\n-505 75\n-888 10\n-856 2\n-503 73\n-745 3\n-903 25\n-897 1\n-896 2\n-848 10\n-878 50\n-864 2\n0 1000\n-934 6\n-792 4\n-271 153\n-917 1\n-891 3\n-833 107\n-847 3\n-758 2\n-754 2\n-892 2\n-738 2\n-876 2\n-52 64\n-882 2\n-270 154\n-763 3\n-868 72\n-846 4\n-427 3\n-771 3\n-767 17\n-852 2\n-765 1\n-772 6\n-831 1\n-582 2\n-910 6\n-772 12\n-764 2\n-907 9\n-909 7\n-578 2\n-872 2\n-848 2\n-528 412\n-731 3\n-879 1\n-862 4\n-909 1\n16 4\n-779 1\n-654 68\n510 490\n-921 3\n-773 5\n-653 69\n-926 2\n-737 3\n-919 1\n-841 1\n-863 3';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Виходи: 105

Попередня версія

C=S.split('\n');N=1+C.shift()*1;s=[];C.map(x=>x.split(' ')).map(x=>[w=x[1]*1,x[i=0]*1+w]).sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d).map(x=>{while(i&&s[i-1][1]<x[1])N+=s[--i][0]?0:1;i&&(s[i-1][0]-=x[0]);s[i++]=x});while(i)N+=s[--i][0]?0:1

З коментарями:

C=S.split('\n');                    // Split the input into an array on the newlines.
                                    // O(N)
N=1+C.shift()*1;                    // Remove the head of the array and store the value as
                                    // if there are N disjoint circles then there will be
                                    // N+1 regions.
                                    // At worst O(N) depending on how .shift() works.
s=[];                               // Initialise an empty stack.
                                    // O(1)
C .map(x=>x.split(' '))             // Split each line into an array of the two values.
                                    // O(1) per line = O(N) total.
  .map(x=>[w=x[1]*1,x[i=0]*1+w])    // Re-map the split values to an array storing the
                                    // radius and the right boundary.
                                    // O(1) per line = O(N) total.

  .sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d)
                                    // Sort the circles on increasing left boundary and
                                    // then descending radius.
                                    // O(1) per comparison = O(N.log(N)) total.
  .map(x=>{                         // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

Загальна часова складність становить O (N) для всього, крім сорту, який є O (N.log (N)) - проте, замінивши це сортування відра, це зменшить загальну складність до O (N).

Необхідна пам'ять - O (N).

Здогадайтесь, що буде далі у моєму списку Тодо ... сортування відра менше ніж 150 символів. Зроблено


Ківш роду має тільки середню складність O(n)(насправді O(n+k)), але O(n^2)і в O(n log n)гіршому випадку в залежності від алгоритму сортування , використовуваного в ковші, так що вам потрібно зробити , це в 50 символів.
Мартін Ендер

@ m.buettner - сортування відра можна виконати в найгіршому випадку (N). Він спирається на ретельний вибір відра та алгоритм O (1) для призначення відра. Я робив це раніше (і довів це), і мені просто потрібно перенести код у JavaScript. Вищенаведений алгоритм - це вже O (N.log (N)), тому єдиним удосконаленням є отримання алгоритму сортування O (N).
MT0

Мене зацікавить цей доказ і відповідний вибір відра. :)
Мартін Ендер

cs.princeton.edu/~dpd/Papers/SCG-09-invited/… (на стор. 556) дає приклад сортування O (N) відра. archive.org/stream/PlanarityTestingByPathAddition/… (стор. 75) наводить приклад комбінованого пошуку та відтворення DFS у поєднанні O (N) (складність часу обговорюється на сторінці 76).
MT0

1
@ Mt0 затримайтеся там, ви можете прочитати моє доповнення до розділу складності питання. З необмеженими числами сортування за лінійним часом, безумовно, неможливо
Ніклас Б.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.