pub struct DoublyLinkedList {
prev: Vec<usize>,
next: Vec<usize>,
}Expand description
Manages only prev/next links of indices.
usize::MAX means no previous or next index.
Fields§
§prev: Vec<usize>§next: Vec<usize>Implementations§
Source§impl DoublyLinkedList
impl DoublyLinkedList
Sourcepub fn new(n: usize) -> Self
pub fn new(n: usize) -> Self
Examples found in repository?
crates/competitive/src/combinatorial_optimization/maximum_scoring_segment_sets.rs (line 68)
8pub fn maximum_scoring_segment_sets<T>(scores: &[T]) -> Vec<T>
9where
10 T: Clone + Ord + Zero + Add<Output = T> + Neg<Output = T>,
11{
12 let n = scores.len();
13 let zero = T::zero();
14 let mut positive_sum = zero.clone();
15 let mut nonnegative_count = 0;
16 let mut negative_scores = Vec::with_capacity(n);
17 let mut blocks: Vec<T> = Vec::with_capacity(n);
18
19 for score in scores {
20 let ordering = score.cmp(&zero);
21 match ordering {
22 Ordering::Greater => {
23 positive_sum = positive_sum + score.clone();
24 nonnegative_count += 1;
25 }
26 Ordering::Equal => {
27 nonnegative_count += 1;
28 continue;
29 }
30 Ordering::Less => negative_scores.push(Reverse(score.clone())),
31 }
32
33 if let Some(last) = blocks.last_mut()
34 && ((*last).cmp(&zero) == Ordering::Greater) == (ordering == Ordering::Greater)
35 {
36 *last = last.clone() + score.clone();
37 } else {
38 blocks.push(score.clone());
39 }
40 }
41
42 if blocks.first().is_some_and(|score| score < &zero) {
43 blocks.remove(0);
44 }
45 if blocks.last().is_some_and(|score| score < &zero) {
46 blocks.pop();
47 }
48
49 let mut result = vec![zero.clone(); n + 1];
50 let segment_count = blocks.len().div_ceil(2);
51
52 for value in &mut result[segment_count..=nonnegative_count] {
53 value.clone_from(&positive_sum);
54 }
55
56 negative_scores.sort_unstable();
57 let mut score_with_negatives = positive_sum.clone();
58 for (offset, Reverse(score)) in negative_scores.into_iter().enumerate() {
59 score_with_negatives = score_with_negatives + score;
60 result[nonnegative_count + offset + 1].clone_from(&score_with_negatives);
61 }
62
63 if segment_count <= 1 {
64 return result;
65 }
66
67 let block_count = blocks.len();
68 let mut links = DoublyLinkedList::new(block_count);
69 for index in 1..block_count {
70 links.link(index - 1, index);
71 }
72
73 let absolute = |value: &T| {
74 if value < &zero {
75 -value.clone()
76 } else {
77 value.clone()
78 }
79 };
80 let mut weights: Vec<_> = blocks.iter().map(|block| Some(absolute(block))).collect();
81 let mut candidates: Vec<_> = (0..block_count).collect();
82
83 let mut losses = Vec::with_capacity(segment_count);
84 for _ in 1..segment_count {
85 let (index, left, right) = loop {
86 let index = candidates
87 .pop()
88 .expect("a live block sequence must have a local minimum");
89 if weights[index].is_none() {
90 continue;
91 }
92 let left = links.prev(index);
93 let right = links.next(index);
94 if (left == usize::MAX || weights[index] <= weights[left])
95 && (right == usize::MAX || weights[index] <= weights[right])
96 {
97 break (index, left, right);
98 }
99 };
100 losses.push(weights[index].take().expect("a local minimum must be live"));
101
102 if left == usize::MAX {
103 links.detach(index);
104 let (_, next) = links.detach(right);
105 weights[right] = None;
106 candidates.push(next);
107 } else if right == usize::MAX {
108 let (prev, _) = links.detach(left);
109 links.detach(index);
110 weights[left] = None;
111 candidates.push(prev);
112 } else {
113 blocks[index] = blocks[left].clone() + blocks[index].clone() + blocks[right].clone();
114 weights[index] = Some(absolute(&blocks[index]));
115 let (prev, _) = links.detach(left);
116 let (_, next) = links.detach(right);
117 weights[left] = None;
118 weights[right] = None;
119 candidates.extend(
120 [prev, index, next]
121 .into_iter()
122 .filter(|&index| index != usize::MAX),
123 );
124 }
125 }
126
127 losses.extend(weights.into_iter().flatten());
128 losses.sort_unstable();
129
130 let mut current_score = positive_sum;
131 for (result, loss) in result[..segment_count].iter_mut().rev().zip(losses) {
132 current_score = current_score + -loss;
133 result.clone_from(¤t_score);
134 }
135 result
136}pub fn is_empty(&self) -> bool
Sourcepub fn prev(&self, index: usize) -> usize
pub fn prev(&self, index: usize) -> usize
Examples found in repository?
crates/competitive/src/combinatorial_optimization/maximum_scoring_segment_sets.rs (line 92)
8pub fn maximum_scoring_segment_sets<T>(scores: &[T]) -> Vec<T>
9where
10 T: Clone + Ord + Zero + Add<Output = T> + Neg<Output = T>,
11{
12 let n = scores.len();
13 let zero = T::zero();
14 let mut positive_sum = zero.clone();
15 let mut nonnegative_count = 0;
16 let mut negative_scores = Vec::with_capacity(n);
17 let mut blocks: Vec<T> = Vec::with_capacity(n);
18
19 for score in scores {
20 let ordering = score.cmp(&zero);
21 match ordering {
22 Ordering::Greater => {
23 positive_sum = positive_sum + score.clone();
24 nonnegative_count += 1;
25 }
26 Ordering::Equal => {
27 nonnegative_count += 1;
28 continue;
29 }
30 Ordering::Less => negative_scores.push(Reverse(score.clone())),
31 }
32
33 if let Some(last) = blocks.last_mut()
34 && ((*last).cmp(&zero) == Ordering::Greater) == (ordering == Ordering::Greater)
35 {
36 *last = last.clone() + score.clone();
37 } else {
38 blocks.push(score.clone());
39 }
40 }
41
42 if blocks.first().is_some_and(|score| score < &zero) {
43 blocks.remove(0);
44 }
45 if blocks.last().is_some_and(|score| score < &zero) {
46 blocks.pop();
47 }
48
49 let mut result = vec![zero.clone(); n + 1];
50 let segment_count = blocks.len().div_ceil(2);
51
52 for value in &mut result[segment_count..=nonnegative_count] {
53 value.clone_from(&positive_sum);
54 }
55
56 negative_scores.sort_unstable();
57 let mut score_with_negatives = positive_sum.clone();
58 for (offset, Reverse(score)) in negative_scores.into_iter().enumerate() {
59 score_with_negatives = score_with_negatives + score;
60 result[nonnegative_count + offset + 1].clone_from(&score_with_negatives);
61 }
62
63 if segment_count <= 1 {
64 return result;
65 }
66
67 let block_count = blocks.len();
68 let mut links = DoublyLinkedList::new(block_count);
69 for index in 1..block_count {
70 links.link(index - 1, index);
71 }
72
73 let absolute = |value: &T| {
74 if value < &zero {
75 -value.clone()
76 } else {
77 value.clone()
78 }
79 };
80 let mut weights: Vec<_> = blocks.iter().map(|block| Some(absolute(block))).collect();
81 let mut candidates: Vec<_> = (0..block_count).collect();
82
83 let mut losses = Vec::with_capacity(segment_count);
84 for _ in 1..segment_count {
85 let (index, left, right) = loop {
86 let index = candidates
87 .pop()
88 .expect("a live block sequence must have a local minimum");
89 if weights[index].is_none() {
90 continue;
91 }
92 let left = links.prev(index);
93 let right = links.next(index);
94 if (left == usize::MAX || weights[index] <= weights[left])
95 && (right == usize::MAX || weights[index] <= weights[right])
96 {
97 break (index, left, right);
98 }
99 };
100 losses.push(weights[index].take().expect("a local minimum must be live"));
101
102 if left == usize::MAX {
103 links.detach(index);
104 let (_, next) = links.detach(right);
105 weights[right] = None;
106 candidates.push(next);
107 } else if right == usize::MAX {
108 let (prev, _) = links.detach(left);
109 links.detach(index);
110 weights[left] = None;
111 candidates.push(prev);
112 } else {
113 blocks[index] = blocks[left].clone() + blocks[index].clone() + blocks[right].clone();
114 weights[index] = Some(absolute(&blocks[index]));
115 let (prev, _) = links.detach(left);
116 let (_, next) = links.detach(right);
117 weights[left] = None;
118 weights[right] = None;
119 candidates.extend(
120 [prev, index, next]
121 .into_iter()
122 .filter(|&index| index != usize::MAX),
123 );
124 }
125 }
126
127 losses.extend(weights.into_iter().flatten());
128 losses.sort_unstable();
129
130 let mut current_score = positive_sum;
131 for (result, loss) in result[..segment_count].iter_mut().rev().zip(losses) {
132 current_score = current_score + -loss;
133 result.clone_from(¤t_score);
134 }
135 result
136}Sourcepub fn next(&self, index: usize) -> usize
pub fn next(&self, index: usize) -> usize
Examples found in repository?
crates/competitive/src/combinatorial_optimization/maximum_scoring_segment_sets.rs (line 93)
8pub fn maximum_scoring_segment_sets<T>(scores: &[T]) -> Vec<T>
9where
10 T: Clone + Ord + Zero + Add<Output = T> + Neg<Output = T>,
11{
12 let n = scores.len();
13 let zero = T::zero();
14 let mut positive_sum = zero.clone();
15 let mut nonnegative_count = 0;
16 let mut negative_scores = Vec::with_capacity(n);
17 let mut blocks: Vec<T> = Vec::with_capacity(n);
18
19 for score in scores {
20 let ordering = score.cmp(&zero);
21 match ordering {
22 Ordering::Greater => {
23 positive_sum = positive_sum + score.clone();
24 nonnegative_count += 1;
25 }
26 Ordering::Equal => {
27 nonnegative_count += 1;
28 continue;
29 }
30 Ordering::Less => negative_scores.push(Reverse(score.clone())),
31 }
32
33 if let Some(last) = blocks.last_mut()
34 && ((*last).cmp(&zero) == Ordering::Greater) == (ordering == Ordering::Greater)
35 {
36 *last = last.clone() + score.clone();
37 } else {
38 blocks.push(score.clone());
39 }
40 }
41
42 if blocks.first().is_some_and(|score| score < &zero) {
43 blocks.remove(0);
44 }
45 if blocks.last().is_some_and(|score| score < &zero) {
46 blocks.pop();
47 }
48
49 let mut result = vec![zero.clone(); n + 1];
50 let segment_count = blocks.len().div_ceil(2);
51
52 for value in &mut result[segment_count..=nonnegative_count] {
53 value.clone_from(&positive_sum);
54 }
55
56 negative_scores.sort_unstable();
57 let mut score_with_negatives = positive_sum.clone();
58 for (offset, Reverse(score)) in negative_scores.into_iter().enumerate() {
59 score_with_negatives = score_with_negatives + score;
60 result[nonnegative_count + offset + 1].clone_from(&score_with_negatives);
61 }
62
63 if segment_count <= 1 {
64 return result;
65 }
66
67 let block_count = blocks.len();
68 let mut links = DoublyLinkedList::new(block_count);
69 for index in 1..block_count {
70 links.link(index - 1, index);
71 }
72
73 let absolute = |value: &T| {
74 if value < &zero {
75 -value.clone()
76 } else {
77 value.clone()
78 }
79 };
80 let mut weights: Vec<_> = blocks.iter().map(|block| Some(absolute(block))).collect();
81 let mut candidates: Vec<_> = (0..block_count).collect();
82
83 let mut losses = Vec::with_capacity(segment_count);
84 for _ in 1..segment_count {
85 let (index, left, right) = loop {
86 let index = candidates
87 .pop()
88 .expect("a live block sequence must have a local minimum");
89 if weights[index].is_none() {
90 continue;
91 }
92 let left = links.prev(index);
93 let right = links.next(index);
94 if (left == usize::MAX || weights[index] <= weights[left])
95 && (right == usize::MAX || weights[index] <= weights[right])
96 {
97 break (index, left, right);
98 }
99 };
100 losses.push(weights[index].take().expect("a local minimum must be live"));
101
102 if left == usize::MAX {
103 links.detach(index);
104 let (_, next) = links.detach(right);
105 weights[right] = None;
106 candidates.push(next);
107 } else if right == usize::MAX {
108 let (prev, _) = links.detach(left);
109 links.detach(index);
110 weights[left] = None;
111 candidates.push(prev);
112 } else {
113 blocks[index] = blocks[left].clone() + blocks[index].clone() + blocks[right].clone();
114 weights[index] = Some(absolute(&blocks[index]));
115 let (prev, _) = links.detach(left);
116 let (_, next) = links.detach(right);
117 weights[left] = None;
118 weights[right] = None;
119 candidates.extend(
120 [prev, index, next]
121 .into_iter()
122 .filter(|&index| index != usize::MAX),
123 );
124 }
125 }
126
127 losses.extend(weights.into_iter().flatten());
128 losses.sort_unstable();
129
130 let mut current_score = positive_sum;
131 for (result, loss) in result[..segment_count].iter_mut().rev().zip(losses) {
132 current_score = current_score + -loss;
133 result.clone_from(¤t_score);
134 }
135 result
136}Sourcepub fn link(&mut self, front: usize, back: usize)
pub fn link(&mut self, front: usize, back: usize)
Links front immediately before back.
Panics if front == back, front already has a next index, or back already has a
previous index.
Examples found in repository?
More examples
crates/competitive/src/combinatorial_optimization/maximum_scoring_segment_sets.rs (line 70)
8pub fn maximum_scoring_segment_sets<T>(scores: &[T]) -> Vec<T>
9where
10 T: Clone + Ord + Zero + Add<Output = T> + Neg<Output = T>,
11{
12 let n = scores.len();
13 let zero = T::zero();
14 let mut positive_sum = zero.clone();
15 let mut nonnegative_count = 0;
16 let mut negative_scores = Vec::with_capacity(n);
17 let mut blocks: Vec<T> = Vec::with_capacity(n);
18
19 for score in scores {
20 let ordering = score.cmp(&zero);
21 match ordering {
22 Ordering::Greater => {
23 positive_sum = positive_sum + score.clone();
24 nonnegative_count += 1;
25 }
26 Ordering::Equal => {
27 nonnegative_count += 1;
28 continue;
29 }
30 Ordering::Less => negative_scores.push(Reverse(score.clone())),
31 }
32
33 if let Some(last) = blocks.last_mut()
34 && ((*last).cmp(&zero) == Ordering::Greater) == (ordering == Ordering::Greater)
35 {
36 *last = last.clone() + score.clone();
37 } else {
38 blocks.push(score.clone());
39 }
40 }
41
42 if blocks.first().is_some_and(|score| score < &zero) {
43 blocks.remove(0);
44 }
45 if blocks.last().is_some_and(|score| score < &zero) {
46 blocks.pop();
47 }
48
49 let mut result = vec![zero.clone(); n + 1];
50 let segment_count = blocks.len().div_ceil(2);
51
52 for value in &mut result[segment_count..=nonnegative_count] {
53 value.clone_from(&positive_sum);
54 }
55
56 negative_scores.sort_unstable();
57 let mut score_with_negatives = positive_sum.clone();
58 for (offset, Reverse(score)) in negative_scores.into_iter().enumerate() {
59 score_with_negatives = score_with_negatives + score;
60 result[nonnegative_count + offset + 1].clone_from(&score_with_negatives);
61 }
62
63 if segment_count <= 1 {
64 return result;
65 }
66
67 let block_count = blocks.len();
68 let mut links = DoublyLinkedList::new(block_count);
69 for index in 1..block_count {
70 links.link(index - 1, index);
71 }
72
73 let absolute = |value: &T| {
74 if value < &zero {
75 -value.clone()
76 } else {
77 value.clone()
78 }
79 };
80 let mut weights: Vec<_> = blocks.iter().map(|block| Some(absolute(block))).collect();
81 let mut candidates: Vec<_> = (0..block_count).collect();
82
83 let mut losses = Vec::with_capacity(segment_count);
84 for _ in 1..segment_count {
85 let (index, left, right) = loop {
86 let index = candidates
87 .pop()
88 .expect("a live block sequence must have a local minimum");
89 if weights[index].is_none() {
90 continue;
91 }
92 let left = links.prev(index);
93 let right = links.next(index);
94 if (left == usize::MAX || weights[index] <= weights[left])
95 && (right == usize::MAX || weights[index] <= weights[right])
96 {
97 break (index, left, right);
98 }
99 };
100 losses.push(weights[index].take().expect("a local minimum must be live"));
101
102 if left == usize::MAX {
103 links.detach(index);
104 let (_, next) = links.detach(right);
105 weights[right] = None;
106 candidates.push(next);
107 } else if right == usize::MAX {
108 let (prev, _) = links.detach(left);
109 links.detach(index);
110 weights[left] = None;
111 candidates.push(prev);
112 } else {
113 blocks[index] = blocks[left].clone() + blocks[index].clone() + blocks[right].clone();
114 weights[index] = Some(absolute(&blocks[index]));
115 let (prev, _) = links.detach(left);
116 let (_, next) = links.detach(right);
117 weights[left] = None;
118 weights[right] = None;
119 candidates.extend(
120 [prev, index, next]
121 .into_iter()
122 .filter(|&index| index != usize::MAX),
123 );
124 }
125 }
126
127 losses.extend(weights.into_iter().flatten());
128 losses.sort_unstable();
129
130 let mut current_score = positive_sum;
131 for (result, loss) in result[..segment_count].iter_mut().rev().zip(losses) {
132 current_score = current_score + -loss;
133 result.clone_from(¤t_score);
134 }
135 result
136}Sourcepub fn cut_before(&mut self, index: usize) -> usize
pub fn cut_before(&mut self, index: usize) -> usize
Sourcepub fn detach(&mut self, index: usize) -> (usize, usize)
pub fn detach(&mut self, index: usize) -> (usize, usize)
Examples found in repository?
crates/competitive/src/combinatorial_optimization/maximum_scoring_segment_sets.rs (line 103)
8pub fn maximum_scoring_segment_sets<T>(scores: &[T]) -> Vec<T>
9where
10 T: Clone + Ord + Zero + Add<Output = T> + Neg<Output = T>,
11{
12 let n = scores.len();
13 let zero = T::zero();
14 let mut positive_sum = zero.clone();
15 let mut nonnegative_count = 0;
16 let mut negative_scores = Vec::with_capacity(n);
17 let mut blocks: Vec<T> = Vec::with_capacity(n);
18
19 for score in scores {
20 let ordering = score.cmp(&zero);
21 match ordering {
22 Ordering::Greater => {
23 positive_sum = positive_sum + score.clone();
24 nonnegative_count += 1;
25 }
26 Ordering::Equal => {
27 nonnegative_count += 1;
28 continue;
29 }
30 Ordering::Less => negative_scores.push(Reverse(score.clone())),
31 }
32
33 if let Some(last) = blocks.last_mut()
34 && ((*last).cmp(&zero) == Ordering::Greater) == (ordering == Ordering::Greater)
35 {
36 *last = last.clone() + score.clone();
37 } else {
38 blocks.push(score.clone());
39 }
40 }
41
42 if blocks.first().is_some_and(|score| score < &zero) {
43 blocks.remove(0);
44 }
45 if blocks.last().is_some_and(|score| score < &zero) {
46 blocks.pop();
47 }
48
49 let mut result = vec![zero.clone(); n + 1];
50 let segment_count = blocks.len().div_ceil(2);
51
52 for value in &mut result[segment_count..=nonnegative_count] {
53 value.clone_from(&positive_sum);
54 }
55
56 negative_scores.sort_unstable();
57 let mut score_with_negatives = positive_sum.clone();
58 for (offset, Reverse(score)) in negative_scores.into_iter().enumerate() {
59 score_with_negatives = score_with_negatives + score;
60 result[nonnegative_count + offset + 1].clone_from(&score_with_negatives);
61 }
62
63 if segment_count <= 1 {
64 return result;
65 }
66
67 let block_count = blocks.len();
68 let mut links = DoublyLinkedList::new(block_count);
69 for index in 1..block_count {
70 links.link(index - 1, index);
71 }
72
73 let absolute = |value: &T| {
74 if value < &zero {
75 -value.clone()
76 } else {
77 value.clone()
78 }
79 };
80 let mut weights: Vec<_> = blocks.iter().map(|block| Some(absolute(block))).collect();
81 let mut candidates: Vec<_> = (0..block_count).collect();
82
83 let mut losses = Vec::with_capacity(segment_count);
84 for _ in 1..segment_count {
85 let (index, left, right) = loop {
86 let index = candidates
87 .pop()
88 .expect("a live block sequence must have a local minimum");
89 if weights[index].is_none() {
90 continue;
91 }
92 let left = links.prev(index);
93 let right = links.next(index);
94 if (left == usize::MAX || weights[index] <= weights[left])
95 && (right == usize::MAX || weights[index] <= weights[right])
96 {
97 break (index, left, right);
98 }
99 };
100 losses.push(weights[index].take().expect("a local minimum must be live"));
101
102 if left == usize::MAX {
103 links.detach(index);
104 let (_, next) = links.detach(right);
105 weights[right] = None;
106 candidates.push(next);
107 } else if right == usize::MAX {
108 let (prev, _) = links.detach(left);
109 links.detach(index);
110 weights[left] = None;
111 candidates.push(prev);
112 } else {
113 blocks[index] = blocks[left].clone() + blocks[index].clone() + blocks[right].clone();
114 weights[index] = Some(absolute(&blocks[index]));
115 let (prev, _) = links.detach(left);
116 let (_, next) = links.detach(right);
117 weights[left] = None;
118 weights[right] = None;
119 candidates.extend(
120 [prev, index, next]
121 .into_iter()
122 .filter(|&index| index != usize::MAX),
123 );
124 }
125 }
126
127 losses.extend(weights.into_iter().flatten());
128 losses.sort_unstable();
129
130 let mut current_score = positive_sum;
131 for (result, loss) in result[..segment_count].iter_mut().rev().zip(losses) {
132 current_score = current_score + -loss;
133 result.clone_from(¤t_score);
134 }
135 result
136}Trait Implementations§
Source§impl Clone for DoublyLinkedList
impl Clone for DoublyLinkedList
Auto Trait Implementations§
impl Freeze for DoublyLinkedList
impl RefUnwindSafe for DoublyLinkedList
impl Send for DoublyLinkedList
impl Sync for DoublyLinkedList
impl Unpin for DoublyLinkedList
impl UnsafeUnpin for DoublyLinkedList
impl UnwindSafe for DoublyLinkedList
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more