Idea: BledDest
Tutorial
Tutorial is loading...
Solution (Neon)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (auto& x : a) cin >> x;
sort(a.begin(), a.end(), greater<int>());
int sum = 0;
for (auto& x : a) {
if (sum + x <= k) sum += x;
else break;
}
cout << k - sum << '\n';
}
}
2042B - Game with Colored Marbles
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (BledDest)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
scanf("%d", &t);
for(int _ = 0; _ < t; _++)
{
int n;
scanf("%d", &n);
vector<int> c(n);
for(int i = 0; i < n; i++)
{
scanf("%d", &c[i]);
--c[i];
}
vector<int> cnt(n);
for(auto x : c) cnt[x]++;
int exactly1 = 0, morethan1 = 0;
for(auto x : cnt)
if (x == 1)
exactly1++;
else if(x > 1)
morethan1++;
printf("%d\n", morethan1 + (exactly1 + 1) / 2 * 2);
}
}
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (Neon)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
string s;
cin >> n >> k >> s;
vector<int> vals;
int sum = 0;
for (int i = n - 1; i > 0; --i) {
sum += (s[i] == '1' ? 1 : -1);
if (sum > 0) vals.push_back(sum);
}
sort(vals.begin(), vals.end());
int ans = 1;
while (k > 0 && !vals.empty()) {
k -= vals.back();
vals.pop_back();
++ans;
}
cout << (k > 0 ? -1 : ans) << '\n';
}
}
Idea: adedalic
Tutorial
Tutorial is loading...
Solution (adedalic)
#include<bits/stdc++.h>
using namespace std;
#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define sz(a) int((a).size())
struct Seg {
int l, r;
bool operator< (const Seg &oth) const {
if (l != oth.l)
return l < oth.l;
return r < oth.r;
};
};
void solve() {
int n;
cin >> n;
vector<Seg> seg(n);
for (int i = 0; i < n; i++)
cin >> seg[i].l >> seg[i].r;
vector<int> ans(n, 0);
for (int k = 0; k < 2; k++) {
vector<int> ord(n);
iota(ord.begin(), ord.end(), 0);
sort(ord.begin(), ord.end(), [&seg](int i, int j){
if (seg[i].l != seg[j].l)
return seg[i].l < seg[j].l;
return seg[i].r > seg[j].r;
});
set<int> bounds;
for (int i : ord) {
auto it = bounds.lower_bound(seg[i].r);
if (it != bounds.end())
ans[i] += *it - seg[i].r;
bounds.insert(seg[i].r);
}
for (auto &s : seg) {
s.l = -s.l;
s.r = -s.r;
swap(s.l, s.r);
}
}
map<Seg, int> cnt;
for (auto s: seg)
cnt[s]++;
for (int i = 0; i < n; i++)
if (cnt[seg[i]] > 1)
ans[i] = 0;
for (int a : ans)
cout << a << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
int t; cin >> t;
while (t--)
solve();
return 0;
}
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (awoo)
#include <bits/stdc++.h>
#define forn(i, n) for (int i = 0; i < int(n); i++)
using namespace std;
vector<vector<int>> g;
struct LCA {
vector<vector<pair<int, int>>> st;
vector<int> pw;
void build(vector<pair<int, int>> a) {
int n = a.size();
int lg = 32 - __builtin_clz(n);
st.resize(lg, vector<pair<int, int>>(n));
st[0] = a;
for (int j = 1; j < lg; ++j) {
for (int i = 0; i < n; ++i) {
st[j][i] = st[j - 1][i];
if (i + (1 << (j - 1)) < n)
st[j][i] = min(st[j][i], st[j - 1][i + (1 << (j - 1))]);
}
}
pw.resize(n + 1);
for (int i = 2; i <= n; ++i)
pw[i] = pw[i / 2] + 1;
}
vector<int> d, fst, par;
vector<pair<int, int>> ord;
int lca(int v, int u) {
int l = fst[v], r = fst[u];
if (l > r) swap(l, r);
++r;
int len = pw[r - l];
assert(len < int(st.size()));
return min(st[len][l], st[len][r - (1 << len)]).second;
}
void init(int v, int p = -1) {
if (fst[v] == -1) fst[v] = ord.size();
ord.push_back({ d[v], v });
for (int u : g[v]) if (u != p) {
par[u] = v;
d[u] = d[v] + 1;
init(u, v);
ord.push_back({ d[v], v });
}
}
LCA(int r = 0) {
int n = g.size();
d.resize(n);
fst.assign(n, -1);
par.assign(n, -1);
ord.clear();
init(r);
build(ord);
}
};
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<int> a(2 * n);
forn(i, 2 * n){
cin >> a[i];
--a[i];
}
g.resize(2 * n);
forn(i, 2 * n - 1){
int v, u;
cin >> v >> u;
--v, --u;
g[v].push_back(u);
g[u].push_back(v);
}
vector<int> l(n, -1), r(n, -1);
forn(i, 2 * n){
if (l[a[i]] == -1) l[a[i]] = i;
else r[a[i]] = i;
}
vector<char> res(2 * n, 1);
forn(rt, 2 * n) if (a[rt] == 0){
LCA d(rt);
vector<int> state(2 * n, 0);
auto mark = [&](int v){
while (v != -1 && state[v] != 1){
state[v] = 1;
v = d.par[v];
}
};
auto markdel = [&](int v){
queue<int> q;
q.push(v);
state[v] = -1;
while (!q.empty()){
int v = q.front();
q.pop();
mark(l[a[v]] ^ r[a[v]] ^ v);
for (int u : g[v]) if (u != d.par[v] && state[u] == 0){
state[u] = -1;
q.push(u);
}
}
};
forn(i, n) mark(d.lca(l[i], r[i]));
for (int i = 2 * n - 1; i >= 0; --i) if (state[i] == 0)
markdel(i);
vector<char> cur(2 * n, 0);
for (int i = 0; i < 2 * n; ++i) if (state[i] == 1)
cur[i] = 1;
reverse(cur.begin(), cur.end());
res = min(res, cur);
}
reverse(res.begin(), res.end());
cout << count(res.begin(), res.end(), 1) << '\n';
forn(i, 2 * n) if (res[i])
cout << i + 1 << " ";
cout << '\n';
return 0;
}
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (Neon)
#include <bits/stdc++.h>
using namespace std;
#define forn(i, n) for (int i = 0; i < int(n); ++i)
const int N = 200 * 1000 + 13;
const int K = 5;
using li = long long;
using mat = array<array<li, K>, K>;
const li INF = 1e18;
int n, q;
li a[N], b[N];
mat t[4 * N];
mat init(li a, li b) {
mat c;
forn(i, K) forn(j, i + 1) c[j][i] = -INF;
c[0][0] = c[2][2] = c[4][4] = 0;
c[0][1] = c[2][3] = a + b;
c[0][2] = c[2][4] = a + b + b;
c[1][1] = c[3][3] = a;
c[1][2] = c[3][4] = a + b;
return c;
}
mat combine(mat a, mat b) {
mat c = init(-INF, -INF);
forn(i, K) forn(j, i + 1) forn(k, j + 1)
c[k][i] = max(c[k][i], a[k][j] + b[j][i]);
return c;
}
void build(int v, int l, int r) {
if (l + 1 == r) {
t[v] = init(a[l], b[l]);
return;
}
int m = (l + r) / 2;
build(v * 2 + 1, l, m);
build(v * 2 + 2, m, r);
t[v] = combine(t[v * 2 + 1], t[v * 2 + 2]);
}
void upd(int v, int l, int r, int p) {
if (l + 1 == r) {
t[v] = init(a[l], b[l]);
return;
}
int m = (l + r) / 2;
if (p < m) upd(v * 2 + 1, l, m, p);
else upd(v * 2 + 2, m, r, p);
t[v] = combine(t[v * 2 + 1], t[v * 2 + 2]);
}
mat get(int v, int l, int r, int L, int R) {
if (L >= R) return init(-INF, -INF);
if (l == L && r == R) return t[v];
int m = (l + r) / 2;
return combine(
get(v * 2 + 1, l, m, L, min(m, R)),
get(v * 2 + 2, m, r, max(m, L), R)
);
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
forn(i, n) cin >> a[i];
forn(i, n) cin >> b[i];
build(0, 0, n);
cin >> q;
forn(_, q) {
int t, x, y;
cin >> t >> x >> y;
--x;
if (t == 1) {
a[x] = y;
upd(0, 0, n, x);
} else if (t == 2) {
b[x] = y;
upd(0, 0, n, x);
} else {
auto res = get(0, 0, n, x, y);
cout << res[0][4] << '\n';
}
}
}
did anybody solved problem C using greedy or binary search only if yes then please provide the code..
.
why is that you only search for those 2 solutions? are you scared of learning a new thing, and a new approach to problems? accept that some problems are weird and require unique solutions. this question cant be binary searched because m+1 does not always yield a better answer than m, and m does not always yield a better answer than m+1. also it cant be solved greedily as you have to consider all suffix differences. stop forcing algorithms just because you're lazy to learn more of them
Hi, can you tell me in which test case m+1 does not give better answer than m.
In all test cases i thought of, m+1 gives better answer. And upon submitting my code, it gives wrong answer on test 2. And in the note it says "50th test case differ" which is not visible.
I did go through the greedy solution and it is indeed intuitive. But I want to know the test case where my binary search fails.
00000000000001, in this case 1 gives the best answer, 2 givea the same answer as 1 and anything over that gives a worse answer.
I still don't understand how the solution related to the question despite it's true, I understand the logic of the code, but I don't get the idea why use that solution. Can you help me.
I visualized this problem completely differently. Lets not think about subarrays, but rather consider the edges of the subarrays as "walls". A worth of a fish is the amount of walls to the left of it(we don't count the edges of the original array itself). So now let's iterate over all positions where we can put the walls, and obviously we can see that we want to put walls where the difference of suf1-suf0 is maximized.
If you ignore the binary string and consider some fix choice of group partition and plot it on the 2D plane where x-axis are fishes and y-axis be there respective value, you would get a bar graph like
then instead of summing over value for each x, let's consider summing them for each y, then you would see if you made a cut between $$$i, i + 1$$$, then it will increase answer by $$$n - i$$$, then it would become much easier to derive the solution in the editorial.
okay, so I understand the first part, but after that I don't understant why the solution do the remaining. I just know that when we pass the array from the end to find the point that are make Bob's score greater than Alice.
To derive the rest of solution, just add the binary string back and you would see the contribution when cutting $$$(i - 1, i)$$$ just change from $$$n - i$$$ to (the number of Bob's fish in $$$[i, n]$$$) — (the number of Alice's fish in $$$[i, n]$$$) and you want to make sum of this stuff no less than $$$k$$$, so you just keep picking the cut point with largest weight until sum of them is no less than $$$k$$$.
okay, thank you.
SO the idea is that, count and take the amount of fishes in indexes that Bob's score exceed Alice's score, then sort the vals list stores those scores diff, then do k — val[i] to take the minimum of groups. Right? So when k get zero before the vals list is empty, how to know that the fished can be devided to such groups. For example, when k = 5 and there are vals list of 5 elements. But after 2 times of subtraction k get zero and there are 3 elements remain in the list. How to know that the fishes can be devide to exactly 3 groups( 2 +1 )?
each val correspond to different cut points, so it's always possible
okay, thank you
Look at what this idiot did.
Instead of using set upper_bound and lower_bound functions, this guy wrote a whole specialized segment tree. https://mirror.codeforces.com/contest/2042/submission/294446705 And it PASSED with only a single penalty.
Guess this is what happens when you solve too many range query problems.
what's the issue, the segtree most likely does have smaller constants, it's not a totally unreasonable decision if you know I think (also idk who asked)
that is me. I am the idiot.
I wrote the segtree because I forgot that lower_bound and upper_bound exist.
Solved too many segtree problems on cses.
Can you explain your approach a bit and also what segtrees are returning as you are passing only index to segtree?
And, personally I believe that it is better to do anything which comes to mind during contest instead of trying to think for best and quickest method (even though lower_bound would have been easier to code :P)
I used two variations of segment trees and used coordinate compression on both of them with a map:
rtree: gives the smallest number greater than equal to x, the given value is compressed but the value stored in the segtree is uncompressed, which is the value to be returned. standard lower_bound on set
ltree: gives the largest value less than equal to x. can be implemented with lower_bound on a set of negative values.
If a value is added to a segtree, the compressed index of the node will store that value, otherwise it will store INT_MIN(INT_MAX) so that we can query max(min) element between 0 and x (x and infinity).
Thanks
.
In problem C tutorial, shouldn't it be $$$0⋅s_{a_1}+(1-0)⋅s_{a_2}+(2-1)⋅s_{a_3}+⋯+s_{a_m}$$$ the resulting sum?
I'd like to add that..
notice you only pick indexes to start a new group where str[i]=='1' and that group can go from i to the end or you can fraction that group into small groups, but for every index you pick to start a new group, the resultant score (diff bob and alice from i to end) or s[i] is positive cuz even if you divide a group into small groups at index i, you will keep the score of s[i]. Example:
$$$n=9, k = 5$$$
011100101
Array $$$s$$$ will be $$${_, 2, 1, 0, -1, 0, 1, 0, 1}$$$, but you are only interested on making groups at indexes where s[i] have positive values. Now you can make a group at index where $$$s[i] = 2$$$ cuz it's the greatest in $$$s$$$. so you make a group between $$$i-1$$$ and $$$i$$$ where $$$i = 1$$$ and we get two points of score, but even if you don't keep the last group you made $$$[i:n)$$$, you'll still keep those two points: now you have groups [0:0] and [1:9). As we still have values on $$$s$$$, let's take the next greatest. Now you have groups [0:0], [1:1], [2:9), cuz in group [2:9) you have +1 of score, and you are still keeping the previous +2 points, even if you divided the [1:9) group.
For problem C, can't we use a prefix array to achieve the same result? Let aj denotes where the jth segment ends.
Then, the sum can be expressed as: 0*pa1 + 1*(pa2 — pa1) + 2*(pa3 — pa2) + .... + (m-1)*(pam — pam-1)
Simplifying, this becomes: -(pa1 + pa2 + ... + pam-1) + (m-1)*pam However, I am unable to eliminate the last m in the equation above. Can someone help?
becomes
which simplifies to
$$$p[n-1]$$$ is clear, you can calculate it. Then sort all other p values and minus the minimum ones first. Of course as you minus, the
m
will also increase.Implementation: 294956283
Not sure why but my equation was coming out to be:
(m-1)*pa[m] - (pa[1] + pa[2] + ... + pa[m-1])
.How did you arrive at your first equation, also what does aj denote in your above equation?
I'm using zero-indexed arrays here and $$$a[j]$$$ denotes the start index of j'th group. This only makes sense for j = 0 -> m-1, so i also define $$$a[m] = n$$$, which is why the last part is $$$p[n - 1]$$$ not $$$p[a[m] - 1]$$$.
If we're using prefix sums the information we have available is the number of fishes to the left of the cuts / gaps / boundaries of the groups. Unfortunately, the multiplier of the contribution of a fish in a group to the score differential is determined by how many cuts it is to the right of. So it's easier to use suffix sums. But we can still deduce the score in a subtractive way using prefix sums, as your formula suggests.
Each fish is first "overvalued" by being multiplied by one less than the number of groups. This is the
(m - 1) * pa[m]
part. To get to the proper score differential, all fish to the left of the first cut, boundary, gap, etc., have their value decremented, same goes for all fish to the left of the second cut, and so on. This is the remainder of the formula.Hope that helps.
Waiting for alternative way of problem D solution (Not using trees... ordered set in C++ or SortedList in python).
Problem D can be solved in linear time complexity without advanced data structures.
Sort $$$(l_i, r_i)$$$ in ascending order of $$$l_i$$$ and descending order of $$$r_i$$$ if $$$l_i$$$ and $$$l_j$$$ are equal. The problem is reduced to finding $$$j$$$ for every $$$i$$$ such that $$$j < i$$$ and $$$r_j \geqslant r_i$$$ (As for the other side of the problem, just reverse the interval as the editorial does). Through sorting, the monotonicity of $$$l$$$ is ensured, and if $$$r$$$ is somehow monotonic, we can solve the problem by a monotonic stack. At first sight the monotonicity of $$$r$$$ might be non-trivial, but consider the fact below: given three indices $$$i < j < k$$$ ($$$l_i < l_j < l_k$$$), if $$$r_i < r_j$$$, $$$i$$$ is impossible to contribute to $$$k$$$. See what I am talking about? By eliminating the elements that will be impossible to do contribution, we construct the monotonicity of $$$r$$$. At last a monotonic stack will be sufficient to solve the problem.
Damn it I forgot the sorting part. It's $$$\mathcal O(n \log n)$$$.
I'll try this approach tmr, good to know. Thanks.
After think through it carefully...
Says if i < j < k and r[j] < r[i] (r[j] is not contributing to an r[i] computation), it doesn't mean we can eliminate it yet since we don't know if there's a future r[k] <= r[j].
So I hardly sees any monotonic stacks will be meaningful, can you elaborate it in code submission? (I can read C++/Python)
You misread my statement. I assumed $$$r_j > r_i$$$ when $$$i < j$$$, which on the opposite when $$$r_j < r_i$$$, $$$i$$$ can contribute to $$$j$$$ and is therefore reserved.
For example:
$$$[1, 8]$$$ cannot contribute to $$$[2, 9]$$$ and is eliminated. Since $$$9 > 8$$$ and $$$1 < 2$$$, if $$$[2, 9]$$$ is unable to do contribution in the future, $$$[1, 8]$$$ is either (remember that $l$s is ascending).
Finally if it still gives you trouble understanding, check out rainboy's submission for elaboration.
After I checkout rainboy's submission, the tricky about segment contribution is applying the monotonic stack for right point, but use the left point to calculate the answer...
I was so obsess on calculate the right segment (like editorial), which result as using data structure is the only choice :(
I see where I went wrong, thanks for sticking with me.
Finally accepted, my last rant is the problem time limit is too strict for python users :(
(I got TLE because I sort one more time too many)
Could someone explain the solution of problem C, or someone give a different approach to problem C
read the comment I wrote above
we can use suffix sums for the same. check out my solution for it
Copy of problem C: 1175D - Array Splitting
For Problem-C, you should use int64.
Problem E can be solved in $$$\Theta(n)$$$ without requiring an $$$O(1)$$$ LCA computation. Instead, we precompute two properties for each subtree: (1) whether it contains all $$$n$$$ distinct values, and (2) whether it contains duplicate values. Using these properties, we can decide whether to select a vertex directly in order.
To facilitate the precomputation, we use the DFS order to represent each subtree as a range and then translate the constraints for a subtree into constraints for its corresponding range. Both properties can be checked in $$$\Theta(n)$$$ using a simple two-pointer technique on the range.
294738728
i tried c using binary search, but couldn't figure out the mistake.. :(
https://shorturl.at/043Sb
For problem C, can't we use a prefix array to achieve the same result? Let aj denotes where the jth segment ends.
Then, the sum can be expressed as: 0*pa1 + 1*(pa2 — pa1) + 2*(pa3 — pa2) + .... + (m-1)*(pam — pam-1)
Simplifying, this becomes: -(pa1 + pa2 + ... + pam-1) + (m-1)*pam However, I am unable to eliminate the last m in the equation above. Can someone help?
For Problem D: What is the reason of the tle ?
Problems like D are often convenient to implement in a way when we group intervals by the beginning of the interval and by the end of the interval and then iterate through all positions:
For this problem it would look like this:
I hope someone finds this useful.
I hope TL of D have to be atleast 4s because if we use segment tree/Fenwick tree instead of ordered set it runs in like 2.2s. so is this tight TL is intended?
can anyone explain solution to problem E, with dsu? (saw it in jiangly`s code)
Problem-E is a very beautiful problem. I like it.
problem E is interesting, thanks you!
If you are asked to find out starting and ending index of each group in problem C then how to do that ?
From the given editorial explanation
Can anyone explain the editorial's solution of Problem C in a bit more intuitive way?
You should learn how to create problem: don't worry i will teach you for free
Hello. I need help in problem D. I am having a Time Complexity of O(NlogN) but I am getting TLE. Can someone please point me out -> TLE Test case 5.
My login: { 1. Sort by start time 2. On every index ask the question, what is time just greater than current(this is our end) and what time is just greater than current that I saw recently(this is our start) 3. Due to the data we have already sorted by start, we get start from Monotonic stack and end from a set or someplace where we can do a query like: give me just greater than the current element 4. Do a difference and that is the answer for that index 5. Put it into our Monotonic stack }
Additional problems: 1. If I use endl or flush at the end I am getting Runtime error: STATUS_ACCESS_VIOLATION -> Runtime error Test case 4 2. If I use endl I am getting WA (weird but OK)
PS: I tried to made my code readable before posting. I hope it helps.
std::lower_bound is only O(log(n)) over random access iterators. Set iterators are NOT random access, so your std::lower_bound call is actually O(n). You probably want to use set::lower_bound instead.
Thank you. Got AC.
thanks, I spent 2 hours trying to figure out why I was getting TLE... thought aswell that lower_bound was O(log(n)) on set
For problem C, I am wondering how
So, each "border" between two groups increases the value of every fish after the border by 1 .
leads to thinking about difference between Alice's fishes and Bob's fishes at every index i.In the coloured marble question, following this logic, wouldnt the input [1 3 1 3 4] result in output 6?
Nope. If she plays optimally, Alice will take marble '4' first (+2 points), then Bob takes marble '3' or '1', let's say Bob takes '3'. So, Alice can take marble '1' or '3' also, let's say she takes '1'(+1 point) . And to make a counter from being get +1 point from taking the all colors of marbles '1', so Bob takes '1', and lastly, alice takes '3' (+1 point) . So, Alice get 4 points.
For the tutorial of C, shouldn't it be
sum is greater than or equal to k
yea but they implemented it differently
Oh my bad, didn't see the implementation