There is a long and thin painting that can be represented by a number line. You are given a 0-indexed 2D integer array paint of length n, where paint[i] = [starti, endi]. This means that on the ith day you need to paint the area betweenstarti and endi.
Painting the same area multiple times will create an uneven painting so you only want to paint each area of the painting at most once.
Return an integer arrayworklogof lengthn, whereworklog[i]is the amount of new area that you painted on theithday.
gantt
title Painting representation across days
dateFormat x
axisFormat x
section Day 0
Paint (1-4): active, 1, 3
section Day 1
Paint (4-7): active, 4, 3
section Day 2
Paint (7-8): active, 7, 1
1
2
3
4
5
6
7
8
9
10
Input: paint =[[1,4],[4,7],[5,8]]Output: [3,3,1]Explanation:
On day 0, paint everything between 1 and 4.The amount of new area painted on day 0is4-1=3.On day 1, paint everything between 4 and 7.The amount of new area painted on day 1is7-4=3.On day 2, paint everything between 7 and 8.Everything between 5 and 7 was already painted on day 1.The amount of new area painted on day 2is8-7=1.
Input: paint =[[1,4],[5,8],[4,7]]Output: [3,3,1]Explanation:
On day 0, paint everything between 1 and 4.The amount of new area painted on day 0is4-1=3.On day 1, paint everything between 5 and 8.The amount of new area painted on day 1is8-5=3.On day 2, paint everything between 4 and 5.Everything between 5 and 7 was already painted on day 1.The amount of new area painted on day 2is5-4=1.
Input: paint =[[1,5],[2,4]]Output: [4,0]Explanation:
On day 0, paint everything between 1 and 5.The amount of new area painted on day 0is5-1=4.On day 1, paint nothing because everything between 2 and 4 was already painted on day 0.The amount of new area painted on day 1is0.
Given a series of intervals [starti, endi], on each day, you need to paint each interval but ensure no overlapping region is painted multiple times. For each interval, calculate the amount of new area painted during that day.
The problem involves tracking painted segments and ensuring that no segment is painted more than once. This can be solved using a Set or a visited status of the painting line.
Key Idea:
Use an array (visited) to represent if a particular area is painted or not. This avoids complex calculations and directly enables checking painted regions.
Steps:
Initialize a sufficiently large boolean array (visited) to represent the painting line as unpainted initially.
Iterate through each interval in paint:
For every point in the interval [starti, endi), check if the region has already been painted using the visited array.
Increment the counter for newly painted areas and mark areas as painted.
classSolution {
publicint[]amountPainted(int[][] paint) {
int maxEnd = 0;
for (int[] p : paint) {
maxEnd = Math.max(maxEnd, p[1]); // Find the maximum range for visited }
boolean[] visited =newboolean[maxEnd]; // To track painted statusint[] ans =newint[paint.length];
for (int i = 0; i < paint.length; i++) {
int start = paint[i][0], end = paint[i][1];
int count = 0;
for (int j = start; j < end; j++) {
if (!visited[j]) { // Paint unvisited segments visited[j]=true;
count++;
}
}
ans[i]= count; // Record newly painted segments for the day }
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
classSolution:
defamountPainted(self, paint: List[List[int]]) -> List[int]:
max_end = max(end for _, end in paint) # Calculate maximum range for visited visited = [False] * max_end # To track painted status of each segment ans: List[int] = []
for start, end in paint:
count =0for i in range(start, end):
ifnot visited[i]: # Only paint unvisited segments visited[i] =True count +=1 ans.append(count) # Record newly painted segments for the dayreturn ans
The segment tree provides an efficient way to manage and query ranges over a number line. In this problem, it is used to track painted areas dynamically and efficiently skip already painted portions of intervals. Here’s the detailed approach:
Representation:
The segment tree is used to store the total number of painted positions in each segment/range, and lazy propagation is used to defer updates to child nodes when necessary.
Implementation Steps:
Update the range [starti, endi): Mark the range as painted.
Query the range [starti, endi): Count how many positions have already been painted.
Subtract Query Result from the Total Range: Compute how many positions are newly painted in the range.
Key Benefits:
Efficient updates and queries over overlapping intervals using lazy propagation.
Reduced complexity compared to naive iteration by splitting the range recursively.
classSegmentTree {
privateint[] tree;
privateint[] lazy;
privateint size;
publicSegmentTree(int size) {
this.size= size;
this.tree=newint[4 * size]; // Segment tree arraythis.lazy=newint[4 * size]; // Lazy propagation array }
publicintupdate(int ind, int left, int right, int ql, int qr) {
// Apply any pending lazy updatesif (lazy[ind]> 0) {
tree[ind]+= (right - left) * lazy[ind]; // Update this rangeif (left != right - 1) { // Mark children for lazy updates lazy[2 * ind + 1]+= lazy[ind];
lazy[2 * ind + 2]+= lazy[ind];
}
lazy[ind]= 0; // Clear pending updates for this node }
// No overlap caseif (qr <= left || right <= ql) {
return 0;
}
// Complete overlap caseif (ql <= left && right <= qr) {
int newPainted = (right - left) - tree[ind]; // Calculate new painted area tree[ind]= right - left; // Mark this range as fully paintedif (left != right - 1) { // Mark children for lazy updates lazy[2 * ind + 1]+= 1;
lazy[2 * ind + 2]+= 1;
}
return newPainted;
}
// Partial overlap case: split into childrenint mid = (left + right) / 2;
int leftPainted = update(2 * ind + 1, left, mid, ql, qr);
int rightPainted = update(2 * ind + 2, mid, right, ql, qr);
tree[ind]= tree[2 * ind + 1]+ tree[2 * ind + 2]; // Update current node based on childrenreturn leftPainted + rightPainted;
}
}
classSolution {
publicint[]amountPainted(int[][] paint) {
int maxEnd = 0;
for (int[] p : paint) {
maxEnd = Math.max(maxEnd, p[1]);
}
SegmentTree segTree =new SegmentTree(maxEnd);
int[] ans =newint[paint.length];
for (int i = 0; i < paint.length; i++) {
int start = paint[i][0];
int end = paint[i][1];
// Update the range and get the number of newly painted segments ans[i]= segTree.update(0, 0, segTree.size, start, end);
}
return ans;
}
}
classSegmentTree:
def __init__(self, size: int):
self.size = size
self.tree = [0] * (4* size) # Segment tree array self.lazy = [0] * (4* size) # Lazy propagation arraydefupdate(self, ind: int, left: int, right: int, ql: int, qr: int) -> int:
# Apply any pending lazy updatesif self.lazy[ind] >0:
self.tree[ind] += (right - left) * self.lazy[ind] # Update this rangeif left != right -1: # Mark children for lazy updates self.lazy[2* ind +1] += self.lazy[ind]
self.lazy[2* ind +2] += self.lazy[ind]
self.lazy[ind] =0# Clear pending updates for this node# No overlap caseif qr <= left or right <= ql:
return0# Complete overlap caseif ql <= left and right <= qr:
new_painted = (right - left) - self.tree[ind] # Calculate new painted area self.tree[ind] = right - left # Mark this range as fully paintedif left != right -1: # Mark children for lazy updates self.lazy[2* ind +1] +=1 self.lazy[2* ind +2] +=1return new_painted
# Partial overlap case: split into children mid = (left + right) //2 left_painted = self.update(2* ind +1, left, mid, ql, qr)
right_painted = self.update(2* ind +2, mid, right, ql, qr)
self.tree[ind] = self.tree[2* ind +1] + self.tree[2* ind +2] # Update current node based on childrenreturn left_painted + right_painted
classSolution:
defamountPainted(self, paint: List[List[int]]) -> List[int]:
max_end = max(end for _, end in paint) # Compute maximum end for segment tree size seg_tree = SegmentTree(max_end)
ans: List[int] = []
for start, end in paint:
# Update the range and get the number of newly painted segments newly_painted = seg_tree.update(0, 0, seg_tree.size, start, end)
ans.append(newly_painted)
return ans