Use this to learn the idea, then write your own version.
1struct SegmentTree {2 public:3 explicit SegmentTree(int n)4 : n(n), treeIntervalCounts(4 * n), treeIntervalLengths(4 * n) {}5 6 7 void add(int i, int val) {8 add(0, 0, n - 1, i, val);9 }10 11 12 int queryIntervalCounts(int i) const {13 return query(treeIntervalCounts, 0, 0, n - 1, i, n - 1);14 }15 16 17 int queryIntervalLengths(int i) const {18 return query(treeIntervalLengths, 0, 0, n - 1, i, n - 1);19 }20 21 private:22 const int n;23 vector<int> treeIntervalCounts;24 vector<int> treeIntervalLengths;25 26 void add(int treeIndex, int lo, int hi, int i, int val) {27 if (lo == hi) {28 treeIntervalCounts[treeIndex] += val;29 treeIntervalLengths[treeIndex] = treeIntervalCounts[treeIndex] * i;30 return;31 }32 const int mid = (lo + hi) / 2;33 if (i <= mid)34 add(2 * treeIndex + 1, lo, mid, i, val);35 else36 add(2 * treeIndex + 2, mid + 1, hi, i, val);37 treeIntervalCounts[treeIndex] =38 merge(treeIntervalCounts[2 * treeIndex + 1],39 treeIntervalCounts[2 * treeIndex + 2]);40 treeIntervalLengths[treeIndex] =41 merge(treeIntervalLengths[2 * treeIndex + 1],42 treeIntervalLengths[2 * treeIndex + 2]);43 }44 45 int query(const vector<int>& tree, int treeIndex, int lo, int hi, int i,46 int j) const {47 if (i <= lo && hi <= j) 48 return tree[treeIndex];49 if (j < lo || hi < i) 50 return 0;51 const int mid = (lo + hi) / 2;52 return merge(query(tree, treeIndex * 2 + 1, lo, mid, i, j),53 query(tree, treeIndex * 2 + 2, mid + 1, hi, i, j));54 }55 56 int merge(int left, int right) const {57 return left + right;58 }59};60 61class Solution {62 public:63 vector<int> numberOfAlternatingGroups(vector<int>& colors,64 vector<vector<int>>& queries) {65 const int n = colors.size();66 vector<int> ans;67 vector<int> arr{colors};68 SegmentTree tree(2 * n - 1);69 set<pair<int, int>> intervals;70 71 arr.insert(arr.end(), colors.begin(), colors.end());72 73 74 int start = 0;75 for (int i = 1; i < 2 * n - 1; ++i)76 if (arr[i] == arr[i - 1]) {77 insert(intervals, {start, i - 1}, tree, n);78 start = i;79 }80 insert(intervals, {start, 2 * n - 2}, tree, n);81 82 for (const vector<int>& query : queries)83 if (query[0] == 1) {84 const int sz = query[1];85 const pair<int, int>& intervalWithN = findInterval(intervals, n);86 const int numAlternatingGroups =87 getNumAlternatingGroups(sz, intervalWithN, tree, n);88 ans.push_back(numAlternatingGroups);89 } else {90 const int index = query[1];91 const int color = query[2];92 if (arr[index] == color)93 continue;94 update(intervals, index, color, arr, tree, n);95 if (index < n - 1)96 update(intervals, index + n, color, arr, tree, n);97 }98 99 return ans;100 }101 102 private:103 104 int getNumAlternatingGroups(int sz, const pair<int, int>& intervalWithN,105 const SegmentTree& tree, int n) {106 const int numIntervals = tree.queryIntervalCounts(sz);107 const int sumIntervals = tree.queryIntervalLengths(sz);108 109 110 111 112 const int numAlternatingGroups =113 sumIntervals - numIntervals * sz + numIntervals;114 115 116 const auto& [l, r] = intervalWithN;117 118 119 120 121 if (l >= n || r - l + 1 < sz)122 return numAlternatingGroups;123 124 125 if (r >= n) { 126 127 const int nonDuplicateGroups = n - l;128 129 const int numGroups = (r - l + 1) - sz + 1;130 return numAlternatingGroups - max(0, numGroups - nonDuplicateGroups);131 }132 return numAlternatingGroups;133 }134 135 136 void insert(set<pair<int, int>>& intervals, const pair<int, int>& interval,137 SegmentTree& tree, int n) {138 intervals.insert(interval);139 if (interval.first < n)140 tree.add(interval.second - interval.first + 1, 1);141 }142 143 144 void remove(set<pair<int, int>>& intervals, const pair<int, int>& interval,145 SegmentTree& tree, int n) {146 intervals.erase(interval);147 if (interval.first < n)148 tree.add(interval.second - interval.first + 1, -1);149 }150 151 152 pair<int, int> findInterval(const set<pair<int, int>>& intervals,153 int target) {154 auto it = intervals.upper_bound({target, INT_MAX});155 return (*--it);156 }157 158 159 160 void update(set<pair<int, int>>& intervals, int index, int color,161 vector<int>& arr, SegmentTree& tree, int n) {162 arr[index] = color;163 164 const pair<int, int> intervalWithIndex = findInterval(intervals, index);165 remove(intervals, intervalWithIndex, tree, n);166 auto [start, end] = intervalWithIndex;167 168 169 170 if (start < index && index < end) {171 insert(intervals, {start, index - 1}, tree, n);172 insert(intervals, {index, index}, tree, n);173 insert(intervals, {index + 1, end}, tree, n);174 return;175 }176 177 178 179 if (start == index && index < end)180 insert(intervals, {start + 1, end}, tree, n);181 182 183 184 if (start < index && index == end)185 insert(intervals, {start, end - 1}, tree, n);186 187 start = index;188 end = index;189 vector<pair<int, int>> intervalsToRemove;190 191 auto it = intervals.upper_bound({index, INT_MAX});192 193 for (auto lit = it; lit != intervals.begin();) {194 --lit;195 if (arr[lit->second] == arr[start]) 196 break;197 intervalsToRemove.push_back(*lit);198 start = lit->first;199 }200 201 for (auto rit = it; rit != intervals.end(); ++rit) {202 if (arr[rit->first] == arr[end]) 203 break;204 intervalsToRemove.push_back(*rit);205 end = rit->second;206 }207 208 for (const pair<int, int>& interval : intervalsToRemove)209 remove(intervals, interval, tree, n);210 211 insert(intervals, {start, end}, tree, n);212 }213};214