g | x | w | all
Bytes Lang Time Link
150Python 3250529T203529ZCrSb0001
nanGo250530T065641ZAhamad
01505AB1E250530T074529ZKevin Cr
094JavaScript Node.js250530T042830Zl4m2
019Pyth250529T215813ZCursorCo
028Uiua 0.17.0dev.1250529T165410ZTbw

Python 3, 169 163 160 151 150 bytes

-6 bytes thanks to @l4m2 (comment link)
-3 bytes

-9 bytes thanks to @mousetail (OP) (comment link)
-1 bytes thanks to @l4m2 (comment link)

def f(m):
 c=len(m);l=v=[2]*c
 while v:
  for i,u,e,o in zip(R:=range(v:=0,c),m,l,p:=[sum(l[:i])for i in R]):
   if(p[u]-o)**2>>e:l[v:=i]+=2
 return p

Outputs the absolute locations.


Previous versions

A (small) collection of some previous iterations of the current code that I had when before each time I was about to post, I thought of another byte save. This is aside from the 169 byte version - the first iteration I actually managed to publish - and following golfs that end up here.

For example, when I was about to post the 200-byte version, I re-read the question and realized I only had to only output 1 of the absolute locations, lengths, and jump distances. This led to my first published version for 169 bytes.

I have double checked that all versions - including the current version - pass all the test-cases that the OP has set.

151 bytes

def f(m):
 c=len(m);l=v=[2]*c
 while v:
  for i,u,e,o in zip(R:=range(v:=0,c),m,l,p:=[sum(l[:i])for i in R]):
   if(p[u]-o)**2>>e:l[i]+=2;v=1
 return p

160 bytes

def f(m):
 c=len(m);l,v=[2]*c,1
 while v:
  v=0
  for i,u,e,o in zip(R:=range(c),m,l,p:=[sum(l[:i])for i in R]):
   if(p[u]-o)**2>>e:l[i]+=2;v=1;break
 return p

163 bytes

def f(m):
 c=len(m);l,v,R=[2]*c,0,range(c)
 while~-v:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if(p[u]-o)**2>>e:l[i]+=2;v=0;break
 return p

169 bytes

def f(m):
 c=len(m);l,v,R=[2]*c,0,range(c)
 while~-v:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if abs(p[u]-o)>>(e>>1):l[i]+=2;v=0;break
 return p

200 bytes

def f(m):
 c=len(m);l,v,R=[2]*c,0,range(c)
 while~-v:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if abs(p[u]-o)>>(e//2):l[i]+=2;v=0;break
 return p,l,[p[u]-o for u,o in zip(m,p)]

201 bytes

def f(m):
 c=len(m);l,v,R=[2]*c,0,range(c)
 while v<1:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if abs(p[u]-o)>>(e//2):l[i]+=2;v=0;break
 return p,l,[p[u]-o for u,o in zip(m,p)]

202 bytes

def f(m):
 c=len(m);l,v,R=[2]*c,0,range(c)
 while v<1:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if abs(p[u]-o)>=1<<e//2:l[i]+=2;v=0;break
 return p,l,[p[u]-o for u,o in zip(m,p)]

203 bytes

def f(m):
 l,v,R=[2]*len(m),0,range(len(m))
 while v<1:
  v,p=1,[sum(l[:i])for i in R]
  for i,u,e,o in zip(R,m,l,p):
   if abs(p[u]-o)>=1<<e//2:l[i]+=2;v=0;break
 return p,l,[p[u]-o for u,o in zip(m,p)]

213 bytes

def f(m):
 l,v=[2]*len(m),0
 while v<1:
  v,p=1,[sum(l[:i])for i in range(len(m))]
  for i,u,e,o in zip(range(len(m)),m,l,p):
   if abs(p[u]-o)>=2**(e//2):l[i]+=2;v=0;break
 return p,l,[p[u]-o for u,o in zip(m,p)]

Go, 429 397 321 317 283 282 277 bytes

Saved (32+76+4+34+1+5=152) bytes thanks to @ceilingcat

     

Golfed version. Attempt This Online!

func f(m[]int)([]int,[]int,[]int){v,g:=0,func(l[]int)[]int{return make([]int,len(l))}
l:=g(m)
p,o:=l,l
for i:=range l{l[i]=2}
for v<1{v=1
p=g(l)
for i:=range^-len(l){p[i+1]=p[i]+l[i]}
o=g(l)
for i,u:=range m{y:=p[u]-p[i]
o[i]=y
if y*y>>l[i]>0{l[i]+=2
v=0
break}}}
return p,l,o}

Ungolfed version. Attempt This Online!

package main

import (
	"fmt"
	"math"
	"strings"
)

func formatMd(k []interface{}) string {
	var parts []string
	for _, i := range k {
		parts = append(parts, fmt.Sprintf("`%v`", i))
	}
	return strings.Join(parts, "|")
}

func f(m []int) ([]int, []int, []int) {
	lengths := make([]int, len(m))
	for i := range lengths {
		lengths[i] = 2
	}
	
	valid := false
	for !valid {
		valid = true
		positions := make([]int, len(m))
		for i := 1; i < len(m); i++ {
			positions[i] = positions[i-1] + lengths[i-1]
		}
		
		for i, u := range m {
			position := positions[i]
			p2 := positions[u]
			distance := int(math.Abs(float64(p2 - position)))
			if int(math.Pow(2, float64(lengths[i]/2))) <= distance {
				lengths[i] += 2
				valid = false
				break
			}
		}
	}
	
	positions := make([]int, len(m))
	for i := 1; i < len(m); i++ {
		positions[i] = positions[i-1] + lengths[i-1]
	}
	
	offsets := make([]int, len(m))
	for i, u := range m {
		offsets[i] = positions[u] - positions[i]
	}
	
	return positions, lengths, offsets
}

func main() {
	testCases := [][]int{
		{1, 2, 0},
		{2, 2, 0},
		{3, 0, 0, 0},
		{4, 0, 0, 0, 0},
		{8, 0, 6, 8, 8, 0, 7, 8, 0},
	}
	
	for _, tc := range testCases {
		positions, lengths, offsets := f(tc)
		fmt.Printf("|`%v`|%s|\n", tc, formatMd([]interface{}{positions, lengths, offsets}))
	}
}

05AB1E, 16 15 bytes

dΔx.¥DIèαyo@+}·

Outputs the lengths.

Try it online or verify (almost) all test cases (the largest test case is omitted, because it'll time out).

Explanation:

d           # Convert each value in the (implicit) input-list to a 1
            # (by using an >=0 check)
 Δ          # Loop until the result no longer changes:
  x         #  Double each value in the current list (without popping)
   .¥       #  Undelta it (basically the cumulative sums with prepended 0)
     D      #  Duplicate that list
      Iè    #  0-based index the input-list into that copy
        α   #  Take the absolute difference at the same positions with the undelta-list
            #  (which will ignore the additional trailing item of the undelta-list)
   y        #  Push the current list again
    o       #  Take 2 to the power each
         @  #  Do an >= check on the values at the same positions in the lists
          + #  Add these 0s/1s to the current list
 }·         # After the changes-loop: double each value
            # (after which the result is output implicitly)

Try it online with added debug-lines.

JavaScript (Node.js), 94 bytes

x=>(g=_=>t.map((c,i)=>(h=j=>j--&&t[j]+h(j),h(i)-h(x[i]))**2>>c&&g(t[i]+=2)))(t=x.map(_=>2))&&t

Try it online!

Pyth, 19 bytes

u.eyl.Bs:G.*S,bkQm1

Try it online!

Outputs the lengths.

Explanation

u.eyl.Bs:G.*S,bkQm1Q    # implicitly add Q
                        # implicitly assign Q = eval(input())
                 m1Q    # array of ones with length Q
u                       # repeatedly apply lambda G to this until duplicate result is obtained
 .e             Q       #   map lambda b,k over enumerated Q 
             ,bk        #     (b, k)
            S           #     sorted
          .*            #     splat as arguments to
        :G              #     slice G between two indices
       s                #     take the sum
     .B                 #     convert to binary string
    l                   #     take the length
   y                    #     multiply by 2

Uiua 0.17.0-dev.1, 28 bytes SBCS

⍥(↘¯1⊂0\+×2+1⌊ₙ2⌵-⟜≡⌞˜⊡)∞⇡⧻.

Try on Uiua Pad!

Outputs the absolute locations. This code repeatedly recomputes the locations until it stops changing.