Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Forget the actual bulb values for a moment. For every boundary between positions and , mark it bad when . A queried segment is beautiful exactly when it contains no bad boundaries.
Study what flipping one interval does to these boundaries. If both bulbs of an adjacent pair are flipped, their equality relation does not change; the same is true if neither is flipped. Only boundaries crossed by an endpoint of the flipped interval can change.
A flipped interval has at most two endpoint boundaries, so one operation can remove at most two bad boundaries. Therefore, if a query contains bad boundaries, at least operations are necessary.
That lower bound is achievable. List the bad boundaries as . For each pair , flip ; this fixes exactly those two boundaries. If one boundary remains, flip . Thus the exact minimum is .
Build a prefix sum over . For query , the number of bad boundaries is , so print YES exactly when . Each query is now ; no segment-tree circus is required.
The whole problem collapses to one fact: if a queried segment contains equal adjacent pairs, then its exact minimum number of operations is
Once we prove that, static prefix sums handle every query.
Call the boundary between bulbs and bad if
A binary segment is beautiful if and only if none of its internal boundaries are bad. Indeed, once every adjacent pair differs, the segment must be one of the two alternating patterns, depending only on its first bit.
For a query , let
So our job is simply to turn all bad boundaries into good ones.
Suppose we flip a subsegment . Consider any adjacent pair:
00 becomes 11, 11 becomes 00, and unequal pairs stay unequal.Only the boundaries immediately outside the flipped subsegment, between and between , have exactly one endpoint flipped. Therefore one operation changes at most two boundary states inside the queried segment.
Operations extending outside offer no secret loophole: intersecting such an operation with flips exactly the same queried bulbs. We may therefore assume every useful operation lies inside the query.
Since one operation can fix at most two bad boundaries, any solution needs at least
operations.
List the bad boundaries in increasing order:
where boundary lies between bulbs and .
Take two consecutive bad boundaries and and flip
At boundary , only the right bulb is flipped. At boundary , only the left bulb is flipped. Thus both bad boundaries become good. Every boundary strictly between them has both bulbs flipped, so its state is unchanged. No other internal boundary is touched.
This fixes each pair of bad boundaries with one operation. If is odd, one bad boundary remains; flipping
changes that boundary and no other internal boundary of the query.
Hence we can always succeed in
operations. Combined with the lower bound, this is the exact optimum. The interval-flip drama was really just endpoint bookkeeping.
Define
and prefix sums
The bad boundaries internal to have indices , so
The answer is therefore YES exactly when
where the division is integer division. This also handles : then , and a one-bulb segment is already beautiful.
For every query :
Thus every printed answer is correct.
For each test case, preprocessing takes time. Every query takes time, for total time and memory .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, q;
cin >> n >> q;
string s;
cin >> s;
vector<int> pref(n);
for (int i = 1; i < n; ++i) {
pref[i] = pref[i - 1] + (s[i - 1] == s[i]);
}
while (q--) {
int l, r, k;
cin >> l >> r >> k;
int bad = pref[r - 1] - pref[l - 1];
cout << ((bad + 1) / 2 <= k ? "YES\n" : "NO\n");
}
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, q;
cin >> n >> q;
string s;
cin >> s;
vector<int> pref(n);
for (int i = 1; i < n; ++i) {
pref[i] = pref[i - 1] + (s[i - 1] == s[i]);
}
while (q--) {
int l, r, k;
cin >> l >> r >> k;
int bad = pref[r - 1] - pref[l - 1];
cout << ((bad + 1) / 2 <= k ? "YES\n" : "NO\n");
}
}
return 0;
}