JavaScript (ES6) - 255 254 Characters - 100 250 Bonus = 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
Assumes that the input string is in the variable S
and outputs the number of regions to the console.
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).
The time complexity is now O(N).
Test Case 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
Outputs: 3
Test Case 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
Outputs: 5
Test Case 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
Outputs: 6
Test Case 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
Outputs: 11
Test Case 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
Outputs: 105
Previous Version
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
With comments:
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).
The total time complexity is O(N) for everything except the sort which is O(N.log(N)) - however replacing this with a bucket sort, this will reduce the total complexity to O(N).
The memory required is O(N).
Guess what is next on my todo list... bucket sort in less than 150 characters. Done
n log n
bonus? Also, I do have new conceptually new solution. Should I post a new answer of replace the old one? (I'd prefer the former, in case my new solution isn't actually correct) \$\endgroup\$