Special thanks to our hub of testuwuers for contributing solution explanations!
2044A - Easy Problem
Problem Credits: cry
Analysis: macaquedev
For any $$$n$$$, Cube can set $$$a$$$ = any integer between $$$1$$$ and $$$n-1$$$ inclusive, and set $$$b = n - a$$$. $$$a$$$ cannot be less than $$$1$$$, because then it would be non-positive, and $$$a$$$ cannot be greater than $$$n-1$$$, because then $$$b$$$ would be less than $$$1$$$, which would make it non-positive. Therefore the answer is just $$$n-1$$$ for all $$$n$$$.
input = sys.stdin.readline
for _ in range(int(input())):
print(int(input())-1)
2044B - Normal Problem
Problem Credits: Lilypad
Analysis: Lilypad, macaquedev
The letters she reads that comprise string $$$b$$$ are just the letters that comprise string $$$a$$$, flipped left-to-right. This means that 'p' becomes 'q', 'q' becomes 'p', and 'w' stays 'w', since it is vertically symmetrical. The order in which the letters are read is also reversed, because what used to be the left side of string $$$a$$$ gets flipped over to the right side of string $$$b$$$, and vice versa.
We now have an algorithm for constructing string $$$b$$$, which is to iterate from right-to-left on string $$$a$$$, outputting 'p' when there is a 'q', 'q' when there is a 'p', and 'w' when there is a 'w'.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pll pair<ll, ll>
int t;
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> t;
while (t--) {
string s;
cin >> s;
reverse(s.begin(), s.end());
for (char &c : s) if (c == 'q') c = 'p'; else if (c == 'p') c = 'q';
cout << s << '\n';
}
}
2044C - Hard Problem
Problem Credits: cry
Analysis: macaquedev
Let $$$A$$$, $$$B$$$, $$$C$$$ be three sets of monkeys, such that monkeys in $$$A$$$ can only sit in row $$$1$$$, $$$B$$$ in row $$$2$$$, and $$$C$$$ can sit anywhere. It is clear that if there is free space in row $$$1$$$, and there are monkeys left in set $$$A$$$, it is optimal to seat a monkey from set $$$A$$$ onto row $$$1$$$. This is because a monkey from set $$$C$$$ can be seated on either row, and there might be space left on the other row for that same monkey in set $$$C$$$ after you've already seated the monkey from set $$$A$$$. However, this is not the case if you start by seating the monkeys in set $$$C$$$ in the front row, since you might now leave empty seats at the back, but then have monkeys from set $$$A$$$ still left unseated.
Therefore, the strategy is as follows: seat as many monkeys from set $$$A$$$ as you can in the front row, then seat as many monkeys from set $$$B$$$ as you can in the back row, then seat as many monkeys from set $$$C$$$ as you can, and that yields the answer.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin>>tt;
while(tt--)
{
int m,a,b,c;
cin>>m>>a>>b>>c;
int ans=0,rem=0;
ans+=min(m,a);rem+=m-min(m,a);
ans+=min(m,b);rem+=m-min(m,b);
ans+=min(rem,c);
cout<<ans<<'\n';
}
return 0;
}
2044D - Harder Problem
Problem Credits: cry, Proof_by_QED
Analysis: macaquedev
Observe that if you have an array where all elements are unique, they will all have frequency $$$1$$$, therefore they can all be classified as the mode. Therefore, it follows that the strategy for the construction is to just construct an array where for each prefix, the last element of this prefix appears in the array at least once. An easy way of doing is this is such:
For each element $$$a_i$$$, if this value has appeared previously in the array (you can use a set to check this), set $$$b_i$$$ equal to some random integer that isn't used elsewhere in the list $$$a$$$, and keep going. Otherwise, set $$$b_i = a_i$$$.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin>>tt;
while(tt--)
{
int n;
cin>>n;
vector<int> a(n+1),b(n);
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(!a[x])
{
b[i]=x;
a[x]=1;
}
}
queue<int> q;
for(int i=1;i<=n;i++)
if(!a[i])
q.push(i);
for(int i=0;i<n;i++)
{
if(!b[i])
{
b[i]=q.front();
q.pop();
}
}
for(int i=0;i<n;i++)
cout<<b[i]<<" \n"[i==n-1];
}
return 0;
}
2044E - Insane Problem
Problem Credits: Proof_by_QED,Lilypad
Analysis: macaquedev, chromate00
Clearly, trying to bruteforce over all possible values of $$$x$$$ or $$$y$$$ is too slow, because the bounds are $$$1 \leq l_1 \leq r_1 \leq 10^9$$$. However, there is another variable that you can actually bruteforce over — and that is $$$n$$$. This is because exponentiation famously makes numbers very big very quickly — and if we set $$$k$$$ as small as possible (i.e. $$$2$$$), we only need to check $$$1 \leq n \leq 32$$$. This is because $$$2^{32} \gt 10^9$$$, so there cannot possibly be any solutions for $$$n \gt 32$$$ for any $$$k$$$.
Now, let's rephrase the problem. We need to find pairs $$$(x, y)$$$ such that $$$x \cdot k^n = y$$$. Now, we can check every value of $$$n$$$ from $$$1$$$ to $$$32$$$, and for each, binary search to find the smallest $$$x$$$ such that $$$y$$$ fits the conditions, and the largest $$$x$$$. Now, we can subtract these two values and add this to the answer.
Note that we do not need to care about more than $$$32$$$ different values of $$$k^n$$$, because obviously $$$k^{32} \ge 2^{32} \gt 10^9$$$. From here and on, we focus on solving for only one value of $$$k^n$$$.
When $$$k^n$$$ is fixed and you are given $$$\frac{y}{x}=k^n$$$, notice $$$y$$$ is fixed as $$$x k^n$$$. Therefore, if we count the values $$$x$$$ such that $$$y$$$ is in the given interval as well, we will be properly counting the ordered pairs.
Formally, this condition can be cleared out as:
- $$$l_2 \le x k^n \le r_2$$$
- $$$\frac{l_2}{k^n} \le x \le \frac{r_2}{k^n}$$$
- Because $$$x$$$ is an integer, $$$\left \lceil {\frac{l_2}{k^n}} \right \rceil \le x \le \left \lfloor {\frac{r_2}{k^n}} \right \rfloor$$$
Thus, when we intersect the two intervals, we get the following interval at last.
Compute the size of this interval for all $$$k^n$$$ (at most $$$32$$$ values) and the answer can be found.
Do note the following details while implementing:
- When $$$r \lt l$$$, the size of the interval is $$$0$$$, not negative.
- Beware of overflows. Dealing with big integers can be helpful in avoiding this, but it may make your solution slow.
- Do not round up a fraction using the
ceilfunction; This has been a recurring issue in almost every Div.4!
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin>>tt;
while(tt--)
{
ll k,l1,r1,l2,r2;
cin>>k>>l1>>r1>>l2>>r2;
ll kn=1,ans=0;
for(int n=0;r2/kn>=l1;n++)
{
ans+=max(0ll,min(r2/kn,r1)-max((l2-1)/kn+1,l1)+1ll);
kn*=k;
}
cout<<ans<<'\n';
}
return 0;
}
2044F - Easy Demon Problem
Problem Credits: chromate00, Proof_by_QED
Analysis: DivinePunishment
This is an anti-hash test for python sets and dictionaries. Before you call us evil, we saved you from getting hacked in open hack phase. Beware!
Let's denote the beauty of the matrix as $$$B$$$, and denote $$$\text{SumA}$$$ as the sum of all the elements in the array $$$a$$$, and $$$\text{SumB}$$$ as the sum of all the elements in the array $$$b$$$.
Before applying an operation, the beauty of the matrix can be expressed as:
$$$B = b_1 \cdot a_1 + b_1 \cdot a_2 + b_1 \cdot a_3 + b_2 \cdot a_1 + b_2 \cdot a_2 + \ldots$$$
After factoring, this simplifies to:
$$$ B = b_1 \cdot (a_1 + a_2 + a_3 + \ldots) + b_2 \cdot (a_1 + a_2 + a_3 + \ldots) + \ldots $$$
Further factoring gives:
$$$ B = (a_1 + a_2 + a_3 + a_4 + \ldots) \cdot (b_1 + b_2 + b_3 + \ldots) $$$
This can be written as:
$$$ B = \text{SumA} \cdot \text{SumB}$$$
Now, consider the effect of an operation on a column $$$C$$$. The beauty decreases by $$$A_c \cdot \text{SumB}$$$. Similarly, when an operation is done on a row $$$R$$$, the beauty decreases by $$$B_r \cdot \text{SumA}$$$.
An important observation is that the element at position $$$(r, c)$$$ is counted twice, so we must account for this in the formula.
After considering this, let the beauty after the operations be denoted as $$$X$$$. Using the observations above:
$$$X = B - (b_i \cdot \text{SumA} + a_j \cdot \text{SumB} - a_j \cdot b_i)$$$
Simplifying further:
$$$X = \text{SumA} \cdot \text{SumB} - b_i \cdot \text{SumA} - a_j \cdot \text{SumB} + a_j \cdot b_i$$$
Factoring terms, we obtain:
$$$X = \text{SumA} \cdot (\text{SumB} - b_i) - a_j \cdot (\text{SumB} - b_i)$$$
Finally:
$$$X = (\text{SumB} - b_i) \cdot (\text{SumA} - a_j)$$$
At this stage, it is sufficient to iterate over the divisors of $$$X$$$. For each ordered pair of divisors whose product is $$$X$$$, we check whether the required values of $$$\text{SumB} - b_i$$$ and $$$\text{SumA} - a_j$$$ can be achieved.
This can be implemented using a simple map or boolean vector for faster computation, although such optimization is not required for this problem.
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define int long long
#define vt vector
#define endl "\n"
const int N = 4e5 + 5;
bool apos[N], aneg[N], bpos[N], bneg[N], posspos[N], possneg[N];
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
int n,m,q;
cin >> n >> m >> q;
vector<int> a(n), b(m);
int asum = 0, bsum = 0;
F0R(i, n) {
cin >> a[i];
asum += a[i];
}
F0R(i, m) {
cin >> b[i];
bsum += b[i];
}
F0R(i, n) {
if(abs(asum-a[i]) < N) {
if(asum-a[i]<0) aneg[a[i]-asum]=true;
else apos[asum-a[i]]=true;
}
}
F0R(i, m) {
if(abs(bsum-b[i]) < N) {
if(bsum-b[i]<0) bneg[b[i]-bsum]=true;
else bpos[bsum-b[i]]=true;
}
}
FOR(i, 1, N) {
FOR(j, 1, N) {
if(i * j > N) break;
if(apos[i]&&bpos[j]) posspos[i*j]=true;
if(apos[i]&&bneg[j]) possneg[i*j]=true;
if(aneg[i]&&bpos[j]) possneg[i*j]=true;
if(aneg[i]&&bneg[j]) posspos[i*j]=true;
}
}
while(q--) {
int x;
cin >> x;
if(x>0) {
if(posspos[x]) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
} else {
if(possneg[-x]) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
}
return 0;
}
2044G1 - Medium Demon Problem (easy version)
Problem Credits: Lilypad
Analysis: macaquedev
This problem deals with a specific subclass of graphs called "functional graphs", also known as "successor graphs". The key feature that they have is that each node only has one successor. Therefore, the graph in the problem will necessarily be split into $$$k \geq 1$$$ components, where each component necessarily contains one cycle, and each node will either be in the cycle, or it will be on a path leading towards the cycle.
Observe that if a node that is not on a cycle currently has a plushie, this plushie will cause the arrangement to be unstable until the plushie reaches the cycle. Proof: suppose node $$$u$$$ has the plushie on day $$$i$$$. On the next day, $$$u$$$ will no longer have this plushie, because they will have passed it down to $$$r_u$$$, therefore, the arrangement has changed. This continues inductively until the plushie reaches the cycle of its component.
From this, we know that the answer is at least the distance of any node to the cycle. Now, since every node in the cycle already has a plushie, we know that these plushies just get passed round and round, so actually, nodes within the cycle cannot change the answer. Therefore, we've already found the final answer.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin>>tt;
while(tt--)
{
int n;
cin>>n;
vector<int> r(n+1),d(n+1);
for(int i=1;i<=n;i++)
{
cin>>r[i];
d[r[i]]++;
}
set<pair<int,int> > s;
for(int i=1;i<=n;i++)
s.insert({d[i],i});
int ans=2;
queue<int> q;
while(!s.empty()&&(*s.begin()).first==0)
{
while(!s.empty()&&(*s.begin()).first==0)
{
int k=(*s.begin()).second;
auto it=s.find({d[r[k]],r[k]});
d[r[k]]--;
if(it!=s.end())
{
s.erase(it);
q.push(r[k]);
}
s.erase(s.begin());
}
while(!q.empty())
s.insert({d[q.front()],q.front()}),q.pop();
ans++;
}
cout<<ans<<'\n';
}
return 0;
}
2044G2 - Medium Demon Problem (hard version)
Problem Credits: Lilypad
Analysis: Proof_by_QED
Note that similarly to G1, once all plushies end up in the hands of spiders who are in a loop, the process becomes stable.
Let's model the input as a collection of rooted forests. For each spider $$$i$$$, if $$$i$$$ is part of a loop, then let's compress the loop into a single node and use that as the root of a tree. Otherwise, if spider $$$i$$$ gives a present to spider $$$r_i$$$, then let's draw an edge from $$$i$$$ to $$$r_i$$$. Now, let $$$i$$$ be any node that is not part of a loop. How long will it take until spider $$$i$$$ runs out of presents? We can see that it is the subtree size of $$$i$$$, as one present leaves the subtree each year.
Thus, our challenge now is to process the nodes in an efficient order such that we can find the subtree size of all nodes. This can be done with topological sorting, which gives us an order that processes all nodes starting from the leaf upwards. After the topological sort, we may do dynamic programming to find subtree sizes of all nodes. Let $$$dp[i]$$$ be the number of days until spider $$$i$$$ runs out of presents. Let's suppose that we already calculated $$$dp[i]$$$ (we initialize it to be $$$1$$$ for all nodes since each spider starts with a present). Then, we should add $$$dp[i]$$$ to $$$dp[r_i]$$$. Doing this and adding up all $$$dp$$$ values of nodes directly before a cycle will yield the answer.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin>>tt;
while(tt--)
{
int n;
cin>>n;
vector<int> r(n+1),d(n+1),v(n+1,1);
for(int i=1;i<=n;i++)
{
cin>>r[i];
d[r[i]]++;
}
set<pair<int,int> > s;
for(int i=1;i<=n;i++)
{
s.insert({d[i],i});
}
int ans=2;
queue<int> q;
while(!s.empty()&&(*s.begin()).first==0)
{
while(!s.empty()&&(*s.begin()).first==0)
{
int k=(*s.begin()).second;
ans=max(ans,v[k]+2);v[r[k]]+=v[k];
auto it=s.find({d[r[k]],r[k]});
d[r[k]]--;
if(it!=s.end())
{
s.erase(it);
q.push(r[k]);
}
s.erase(s.begin());
}
while(!q.empty())
s.insert({d[q.front()],q.front()}),q.pop();
}
cout<<ans<<'\n';
}
return 0;
}
2044H - Hard Demon Problem
Problem Credits: cry
Analysis: chromate00
Consider translating the sum back onto the matrix. For simplicity we discuss about querying the whole matrix.
The sum we would like to find is $$$\sum_i i\cdot A_i$$$. Here, $$$A_i$$$ corresponds to $$$M_{(x,y)}$$$, so we will translate this to $$$\sum_{x,y} i\cdot M_{(x,y)}$$$. The issue left is on the $$$i$$$ multiplied to it.
Remember that we index the entries in increasing order of $$$y$$$, and then increasing order of $$$x$$$. Assuming $$$y$$$ and $$$x$$$ were $$$0$$$-indexed, this will mean entry $$$(x,y)$$$ corresponds to $$$x\cdot n + y$$$ (also $$$0$$$-indexed). You can notice that this naturally corresponds to the order we had defined as well.
Then, what we want to find is $$$\sum_{x,y} (x \cdot n + y + 1)\cdot M_{(x,y)}$$$. Notice $$$x \cdot n$$$, $$$y$$$, $$$1$$$ are independent, and we can split them into sums $$$\sum_x x \cdot n \cdot M_{(x,y)}$$$, $$$\sum_y y \cdot M_{(x,y)}$$$, $$$\sum M_{(x,y)}$$$. Each of these three sums can be precomputed entry by entry, and a 2D prefix sum can solve the answer for the entire matrix.
The query for a submatrix is very similar. Formally, you have to care about:
- That we have $$$y_2-y_1+1$$$ columns instead of $$$n$$$ now;
- That the precomputed values might not start from $$$0$$$ on the first row/column of the query.
Still, these two issues can be fixed using the three sums we have precomputed. The time complexity becomes $$$\mathcal{O}(n^2+q)$$$.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector <ll>;
using ii = pair <ll, ll>;
using vii = vector <ii>;
void tc () {
ll n, Q;
cin >> n >> Q;
vector <vll> mat(n, vll(n));
for (vll &ve : mat) {
for (ll &i : ve) cin >> i;
}
vector <vll> psR(n, vll(n+1)), psRr(n, vll(n+1)), psRc(n+1, vll(n+1)), ps(n+1, vll(n+1)), psRrc(n+1, vll(n+1));
for (ll i = 0; i < n; i++) {
for (ll j = 0; j < n; j++) {
psR[i][j+1] = psR[i][j] + mat[i][j];
}
}
for (ll i = 0; i < n; i++) {
for (ll j = 0; j < n; j++) {
psRr[i][j+1] = psRr[i][j] + mat[i][j]*(j+1);
}
}
for (ll i = 0; i < n; i++) {
for (ll j = 0; j <= n; j++) {
psRc[i+1][j] = psRc[i][j] + psR[i][j]*(i+1);
}
}
for (ll i = 0; i < n; i++) {
for (ll j = 0; j <= n; j++) {
psRrc[i+1][j] = psRrc[i][j] + psRr[i][j];
}
}
for (ll i = 0; i < n; i++) {
for (ll j = 0; j <= n; j++) {
ps[i+1][j] = ps[i][j] + psR[i][j];
}
}
while (Q--) {
ll x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
x1--; y1--; x2--; y2--;
ll ans = 0;
ans += -(ps[x2+1][y2+1]-ps[x2+1][y1]-ps[x1][y2+1]+ps[x1][y1])*x1*(y2-y1+1);
ans += (psRc[x2+1][y2+1] - psRc[x1][y2+1] - (ps[x2+1][y2+1]-ps[x1][y2+1]))*(y2-y1+1);
ans += (psRc[x2+1][y1] - psRc[x1][y1] - (ps[x2+1][y1]-ps[x1][y1]))*-(y2-y1+1);
ans += (ps[x2+1][y2+1]-ps[x1][y2+1])*-y1;
ans += (ps[x2+1][y1]-ps[x1][y1])*y1;
ans += psRrc[x2+1][y2+1] - psRrc[x1][y2+1];
ans +=-(psRrc[x2+1][y1] - psRrc[x1][y1]);
cout << ans << ' ';
}
cout << '\n';
}
int main () {
cin.tie(nullptr) -> sync_with_stdio(false);
ll T; cin >> T; while (T--) { tc(); }
return 0;
}








first ez
when the rating will publish
in 20 min maybe, usually the rating publish before 24 hours pass since the contest started.
It was my first contest so when I get rating do I need to participate more 4 contest?
Same bro I also didn't get any rating
You might have registered as Unrated participant
means??
Some contests allow unrated participants.
So you might have registered as unrated. There comes a checkbox while registering for the contest
I've added my thought process and hints for G1. Medium Demon Problem (easy version) on CF Step
actually, the "easy demon problem" was the hard one
that's right
You can still use the same in-degree idea to solve g2 with minimal changes. You can see my submission.
in your code you're basically looking for the maximum accumulated number of plushies for the vertices outside of a cycle?
yeah basically
Hi, could you explain why you add 1 in this line?
c[adj[cur]] += c[cur]+1;Tried just initializing c with 1 for all nodes and then in the above line just not add 1, but it prints WA, so I don't really know what the intuition behind this is.
Moreover, why add 3 here?
maxi = max(maxi,c[i]+3);Thanks in advance
In my code, I’m accumulating plushies starting from zero. If each plushy should initially start with 1, the first one would have 1, the second would accumulate 2, the third 3, and so on. However, I started with the first one at zero instead. To account for this offset, I’m adding 3 at the end instead of 2. The reason you would add 2 at all is because if the answer is always at least 2.
Alternatively, if you initialize all plushies to 1 from the start, you wouldn’t need to compensate for the initial zero. In that case, you would add 2 instead of 3. AC
My Text Editorial (A-D)
Screencast
I was so stupid on C and D for real :(
I think this is one of the better div4's of recent history.
However, I was very disappointed that my editorial for problem A was edited. In fact, the four most important words in this editorial were removed. Initially, it said "This problem is trivial. For any n,...", but I have been censored, and the first sentence is no longer there.
Freedom of speech is a fundamental human right and I feel violated.
cope and seethe
I think there is some mistake in solution of 2044G1 (medium demon problem easy version). there must be maximum distance of any node to cycle instead of minimum distance. can you please check.
Read again — I never said it was the minimum.
No problem is absolutely trivial. What's trivial for you might not be trivial for someone else.
Besides, saying "This problem is trivial ..." does not add anything in the value of editorial.
are you enjoying being wrong? the word "trivial" just sounds nice
Indeed, I am.
Imo, it is used mostly as a condescending word. Idk why mathematicians are so obsessed with it. Sometimes I'd go to my professor for math help, and I'd show him what I needed help with, and he'd go "oh that's trivial" then tell me how to do it. Why would he say that other than to show off?
Condescending, but also justified. The word "trivial" is reassuring, calming and transformative. I wish everyone used it more.
boy do i love getting TLE'd
Thank you codeforces team. This was my first contest here in cf and i was able to solve 3 problems i was trying to do 5 th question but didn't get how to work with time complexities for such high problems.. Overall beginner friendly.. Thanks in Advance Codeforces team.
wait for next round. its gonna be div(1 + 2). xd xd xd. Fireworks.
All the best.
omg my editorial for F made it uwu
Can you help me debug my solution. 300958196 My approach seems to be the same as the editorial but I seem to get WA on test 38. Seems to be some edge case
ive tried making everything into ll and tried all the c++ compilers and none of it works. i even get tle when putting set instead of ordered set, which is weird. really confused tbh. the logic seems correct as well, so idk
ah okay i found it. you get overflow when using accumulate because you put 0 instead of 0ll. i get tle on test 39 now so either switch to boolean array or use sets less somehow.
Ahh, thanks a bunch dude. You're the best :)
Very creative problem names. (like my variable names)
Thanks for the awesome problem set -_-
I think, D is harder than E and F harder than G1. F — is the best problem, that i have seen on Div4 rounds)
problem f.............................
You do q * n * m operations on your code. This is very big count.
Thanks for the great contest!
Quick question, how are you supposed to round up without using ceil?
$$$\lceil \frac{n}{i} \rceil = \lfloor \frac{n+i-1}{i} \rfloor$$$
you mean n+i-1
thanks, updated
It would be n+i-1 in numerator of RHS
extreme demon where
in div1
Thanks for Lobotomy round , makes my brain FIRE IN THE HOLE.
Thanks for fast editorial , makes my brain WATER ON THE HILL.
As a Geometry Dash player , I'm quite excited to see my favourite game on codeforces.
As a codeforces round contestant , I'm playing Geometry Dash now and beat a easy demon :).
For G2, instead of topological sorting and DP, you can just find all spiders $$$i$$$ such that $$$r_i$$$ is in a cycle and do a simple dfs to find their subtree sizes.
Yes, I think DivinePunishment found that solution and it's a lot nicer.
Yes! exactly what I did.
Or you could start by processing nodes with an in-degree of zero and increment the values of their adjacent nodes by 1.
I had the same approach !
g1 was nice
time was up while doing g2 :(
Can anyone tell me what is wrong with this code in E (binary search):
My code
In binary search:
int val = mid*powval;
powval could be as big as 1e12, and mid could be 1e9. 1e12 * 1e9 = 1e21, and that number overflows long long.
How do I fix that?
You don't need powval to go up to 1e12. I think 1e9 is probably enough.
But This code also doesn't work where powval goes up to 1e9
I think it is strange that your binary search sets left = mid+1 if the condition is met, but sets right = mid-1 if the condition is not met.
Usually, it is either left = mid+1, right = mid
Or: left = mid, right = mid-1
Take a look at your code and see if the error could be related to that.
Doesn't work!
Ok I will just ask ChatGPT then.
Edit: That was no help.
I've been looking at your code since then and I've managed to notice the following things.
1) You would have to do two binary searches, one to find the first x that is valid and another one to find the last x that is valid. It seems like your code assumes x = l1 is always valid, which is wrong.
2) You will not be able to binary search for those 2 x values directly on the interval [l1, r1], because it could happen that there are values x1 < x2 < x3 such that x1 is not valid, x2 is valid and x3 is not valid (i.e., binary search won't work on a non-increasing function). You will have to tighten that search interval, and the way you ensure your interval is scritcly increasing is by searching on
[max(l1, (l2+powval-1)/powval), min(r1, r2/powval)],i.e., the left boundary becomes the first x that you are sure that works, and the right boundary becomes the last x that works.
But now that you already calculated the first and last x that work, you don't even need the binary search anymore, and you already have the values you were searching for.
Below is the link of the submission of this solution. I tried to modify your code as little as possible, and the only thing I modified is in between two comments.
https://mirror.codeforces.com/contest/2044/submission/296764832
can u also tell me whats wrong with submission
You are always iterating with i from 0 to 31, even though k^n may increase much faster than 2^n (and the cap 31 you chose is for the worst case of k = 2). Indeed, it increases so fast that k^i easily overflows long long for some values of k > 2. All you gotta do is something like
because you are always sure that whenever the power is bigger than r2, it will never fit in the interval anyways. That also ensures no overflow will happen, because the maximum r2 multiplied by the maximum k fits in a long long with no problem.
Problem with the MODE was really interesting!
+1
Took me more than 30 minutes, but when I realized, I thought I should kill myself. :)
Wasted time on F thinking about Binary Search, should have skipped to G1. Good learning.
Edit: F is a beauty cud never think thru this approach
Help me With Problem D, please. Is there another way to solve this without using a set?
You can use an array as an alternate hashset. Conceptually you cannot avoid a set because you need to mark appeared numbers.
https://mirror.codeforces.com/contest/2044/submission/296719812
If anybody could tell me the exact case where my code fails, I would really appreciate it! Thanks
PS- This is based on the intervals logic that the author had shared, however I am not able to figure why is it giving a wrong answer on 121st case on Test 2. (1 instead of 0)
Do not use
pow. Multiply manually.$$$l1 * curr_pow$$$ can overflow, also avoid pow function due to floating precision
https://mirror.codeforces.com/contest/2044/submission/296719812
Tried everything, still didn't work. What else could be the reason?
Try this input;
Correct answer is 0. Your code gives 1.
Someone tell me how to solve D if there was only allowed to use the elements of vector a only instead of 1 <= b[i] <= n
that what I was trying to solve for first 40 mins of solving D lol
same here.I was thinking how it can be problem D then I realised I read the statement wrong.
why not to use ceil function?
Ceil has some precision issues. This code shows an example of that:
Output:
You risk precision loss by using
ceil. Especially the round is open hacked, and your risk doubles.Can you explain to me, plz, how to solve F without "yesterday my math teacher showed me some stuff so i will create a problem for that, it will be so cool" observation in the editorial?
"yesterday my brain showed me some stuff so you will have to solve a problem for that, it will be so cool" is what all codeforces rounds are about, cope and seethe
Man, I don't wanna argue about was it difficult to get this idea or not. It's a solid problem no matter what. But if you look at the solutions of participants who had 2 hours instead of several days, you'll see that most of them used another approach that I don't understand. So I want to get it
the 2nd part of the editorial is kinda just extra for people who didnt get it. the B=SumA*SumB is obvious, and if you dont get that, idk. then you just realize that when you make an entire row 0 and an entire column 0, you essentially just make SumA smaller by a[c] and SumB smaller by b[r], so new B=(SumA-a[c])*(SumB-b[c]), and then its clear you can just iterate with divisors. this is the best i could explain without the "math stuff". but i also think your comment is very stupid, since cp is just math with computers
Calling my comment "very stupid" doesn't do you any credit but only shows your rudeness. Also it shows that you're rushing in without figuring things out. I asked for another solution than in editorial. And explanation in editorial is clear for me.
Plz, problemsetters, stop responding for my comments here, because I don't want to argue with you, I want to get another approaches to this problem if there are any. And if my first comment was offending for you, I'm truly sorry, I'm not here for a verbal sparring, and I was genuinely considering my words about math teacher as a mini-joke.
anyone use scc for G problem?
yes, you can refer to my code.
Loved Problem F Solution But during round the thought of factoring the equation didn't come to my mind. so i considered the equation to_remove = total_sum_of_grid minus x and
to_remove = ai*(sumof_b) + bj*(sumof_a) — ai*bj
can we apply binary search on this equation by fixing i on sorted array a and then j on sorted array b?? is it possible to get solution?? i tried but couldn't make it right****
Thanks for bringing this up, I was thinking the same thing! Unfortunately the ai*bj term is really annoying, I don't know how you could binary search with that in there.
we can first fix the index of array a by binary search on a and in the while loop we can manupulate the cofficient of bj as sum_of_a minus a[i] (as we already fixed i) so that we get rid of ai*bj term and now we can binary search on j
i tried it but it is not giving correct answer for sample tests also
For H the following equation might be of help for finding the answer for a general submatrix
We want to find $$$\Sigma_{x,y}((x-x_1)\cdot w + (y-y_1) + 1)\cdot M_{(x,y)}$$$ where $$$w$$$ is the width of the submatrix. Note that $$$x$$$, $$$y$$$, $$$x_1$$$, $$$y_1$$$ are all 0-indexed.
Anyone who wants to solve array version of the H problem.
https://www.hackerrank.com/contests/nitc-icpc-series-1/challenges/array-queries-1
I would suggest, first solve array version, then try to solve the grid one.
Also, in the array version, there is one more problem, where you can do point-update and range query using segment tree.
Can you send the link for the question that involves a segment tree?
Can't find exact one right now.
But replica of it. You can stress test it with the coding given in the stackoverflow.
https://stackoverflow.com/questions/62244057/efficient-way-to-query-and-update-al1-al12-arr-l1
Somewhat similar :
https://www.codechef.com/problems/AGCY
loved g1 and g2. solved g1, didnt have enough time left for g2. great contest!
CYAN, YAY!
Hey, could somebody look at this submission for problem H and tell me why it gives TLE? 296778260 I'm at a loss for words... I already got AC but ONLY after implementing a custom readInt function in C and turning it in with C++20 (GNU C11 gave TLE with exactly the same code).
What am I doing wrong? Firstly, I expected the C version to be faster, but in always TLEd on test #2, while the C++20 code always TLEd on test #4. On my computer it runs fine even with a randomly generated max n/max q tests.
My main suspicion is the fact that I use unsigned long longs or perhaps I'm going out of bounds at some point. I highly doubt it has anything to do with cache misses.
Figured it out...
The major bottleneck here is the input speed. Somehow, scanf ends up being slower than cin... How? I do not know. I always assumed scanf was faster than cin.
I also find it rather strange that when submitted with C11 (with almost identical code to the 4th stated submission), it actually becomes significantly slower (~765ms). I have no idea why. Also, why would the C++20 version with scanf/printf give TLE and the C++17 version not? Finally, since when is cin faster than scanf? Was I just oblivious to this fact or...? Additionally, using clang with -std=c++20 on my computer cin/cout end up begin WAY slower (at around 7.5s) for the random stress test, whilst scanf/printf do fine (at around 700ms).
Takeaways:
i can't believe there is easy medium demon and hard medium demon. just like gepmetry dasj
why did my solution to F get hacked ? (https://mirror.codeforces.com/contest/2044/submission/296732576)
https://mirror.codeforces.com/blog/entry/137306?#comment-1228128 explained here.
Geometry dash????
idk your thoughts on problem F, but to me it's like a 1400, at most 1500. Fun problem though!
I think you overlooked the worst case for the "map" solution. My hack idea for F is to make the slowest case for such solutions, and it caused tons of TLEs.
Let's say $$$SA$$$ is the set of $$$SumA-a_i$$$s and $$$SB$$$ is the set of $$$SumB-b_i$$$s. The most basic way to implement this solution is for each $$$i \cdot j = x$$$ ($$$1 \le i \le \sqrt{x}$$$), to check if any of the following conditions is true:
The order of the four conditions doesn't matter, as long as the answer is "NO", since it will have to verify all of them anyways. However, an important thing here is that each condition actually contains two checks, concatenated by an "and". This means that such codes, in most languages, will be short-circuit-evaluated. So, if none of them is in $$$SA$$$, it will perform only the first check of each condition and move on, without checking the $$$SB$$$ part, resulting only in 4 checks each time.
Therefore, my idea was to query the number with most number of divisors, while letting $$$i$$$, $$$j$$$, $$$-i$$$, $$$-j$$$ are always in $$$SA$$$, while none of them are in $$$SB$$$, and making sure that all $$$2 \cdot 10^5$$$ elements for each array are distinct. This way, I was able to force these solutions to perform 8 checks each time, and as expected, many of the solutions that took a little more than 2 seconds in the original tests, well-exceeded 4 seconds on this hack test.
bruh
How did you generate such a large test case(q<=1e4 and x<=1e5) such that all of i ,j,-i,-j are present is SA and not in Sb?
You can refer to this hack generator.
Basically, we want to aim for $$$SumA = SumB = 0$$$. That'll make it easy for us to work with the elements, because then each element itself would just be the element of $$$SA$$$ and $$$SB$$$ (to be precise, it's the negative value of it but it doesn't really matter since positive and negative are symmetric in this problem).
To do this, we can first put $$$n-1$$$ elements to an array, and then insert the negative of the sum of these $$$n-1$$$ elements. Since we can only use elements within range $$$[-n, n]$$$, the sum of the $$$n-1$$$ elements has to be within that range too. The strategy for this is simple. While we're making these $$$n-1$$$ elements, we pick either a posivie random value or a negative random value based on the current sum. If the sum is negative then we put a positive value, and vice versa. We just need to hold an additional
setto check if the value is duplicated. If the $$$n$$$-th element is to be duplciated, we can remove the $$$n-1$$$-th element and try choosing it again.The only difference between $$$SA$$$ and $$$SB$$$ is that, for $$$SA$$$ we start by inserting every divisors of $$$x$$$ first, while for $$$SB$$$ we avoid such values while picking random values.
Also, you can easily do this without randoms (like you can just put $$$k$$$ and then $$$-k$$$ to keep the sum $$$0$$$), but I prefer using random because for some reason
sets andmaps are fast on most of data that have patterns, and is easy to modify the seed to generate another similar test.Hello djm03178,
The submission using
mapresulted in TLE, as seen here: 296746721.However, the version using
unordered_setpassed successfully, despite performing 8 checks: 296883645.Given that the worst-case time complexity of
unordered_setoperations is O(n). Could you clarify why this difference occurs and howunordered_setis still more efficient in this case?Thanks!
Wow. Changed my solution from map to unordered_map and now it passes. Did no one try hacking hash tables? That's crazy.
In general, unordered_set and unordered_map take O(1) time. But generally there are tests designed against these data structures which make them take O(n) time. Not the case here tho
Yeah I thought the same , I just wanted to know if there are any other reasons , and also when it is beneficial to use map/unordered_map, unordered_set
I think it's impossible to hack
unordered_setin this problem. You can read https://mirror.codeforces.com/blog/entry/132929 . To be short, you need a wider range for the elements than just $$$n$$$ to hack them. We can technically make something that makes the insertion part a little slower, but I'm not sure if we can do much with slowing down the query part at the same time then...Actually, it could be possible, but I'm not too sure. For example in C++20, we can insert multiples of $$$541$$$ into $$$SA$$$ and $$$SB$$$ in both positive and negative directions. Then repeat querying something that will find a lot of numbers that are multiples of $$$541$$$, and from what I found it is $$$194760$$$, which will search $$$48$$$ of them from each of $$$SA$$$ and $$$SB$$$ in total. Looking up other values than multiples of $$$541$$$ will take negligible time.
I don't know how exactly we can control the insertion order so that all elements we try to find will take time as closely as looking up all $$$541$$$ elements, but there likely is a way for this. For $$$SB$$$ we would just need to exclude these values and they will always check all $$$541$$$ elements.
If we naively calculate this, it will be $$$2 \times 541 \times 48 \times 50000 \simeq 2.6 \cdot 10^9$$$. However, the constant for resolving hash collision is relatively tiny, so I can't be sure if this would be enough to exceed 4 seconds.
Ok, I tried it and it looks possible: https://mirror.codeforces.com/contest/2044/hacks/1102766/
We probably just need to find a way to adjust the insertion order to slow down the finding process on $$$SA$$$.
I made it: https://mirror.codeforces.com/contest/2044/hacks/1102768
At first, the plan to force 8 checks wasn't working, because $$$i$$$ and $$$-i$$$ were not in $$$SA$$$ because they were not divisible by $$$k$$$, and therefore it did only 6 checks, skipping two $$$SB$$$ checks. So, instead I sacrificed a bit of hash collisions to insert all $$$i$$$'s and $$$-i$$$'s too, so that all $$$SB$$$ checks will be performed.
I don't know if it's always this simple but inserting the target elements first made the search slow. Reversing the $$$a$$$ array makes it really fast.
This was quite challenging, but man, it's surprising that we made use of the $$$\mathcal{O}(\sqrt{n})$$$ version of the hash hack.
I am kind of late but i think the main problem with your solution is how you are using maps, like every time you do something like this "mpa[d1]" if d1 doesn't exist in the map c++ will create that key and is going to assign it the value 0 by default, the problem here is that it means that every time you access the map in a position that didn't exist before you're increasing the map size and by doing so on each step your map queries will get slower after each query.
I think that with a good construction of queries your maps can eventually have every possible number between -2e5 and 2e5 in addition to probably 2e5 values greater than 2e5, so yeah, probably that's the reason why you were receiving tle, you can look at my solution where i used .count to avoid that problem.
My solution (16 months late but maybe it will help someone in the future i guess)
We missed Insane and Extreme demons from the problem set I guess
I think there is some mistake in solution of 2044G1 (medium demon problem easy version). there must be maximum distance of any node to cycle instead of minimum distance. can someone please check if i am right or wrong.
It's the minimum distance of any node to a cycle, thus it will be the maximum distance overall. The wording is a bit weird but it should be correct.
Hello sir, thankyou to reply. it should be corrected? I am right or wrong?
The wording seems tricky, but it is correct
Could anyone help me with my code? https://mirror.codeforces.com/contest/2044/submission/296745472 codeforces said it has runtime error on test case #10 . But when I try the code and the test case #10 on my pc, also on ideone ( https://ideone.com/eVDhX0 ), I found no error. Is there a fix for my code? I just can't find the error.
F was a type of problem I have never solved till now. Very innovative! Thanks for the problems.
Problem E can also be solved using the technique of solving Diophantine equations. Indeed, iterate over a sequence $$$(k^0, k^1, k^2, \dots, k^n, \dots)$$$ while $$$k^n \leq 10^9$$$. On each iteration we need count how many integer solutions $$$(x, y)$$$ the system
has and sum these values to obtain a final answer. Thus, it is necessary to calculate how many solutions the Diophantine equation $$$x k^n - y = 0$$$ has that satisfy the inequalities $$$l_1 \leq x \leq r_1$$$ and $$$l_2 \leq y \leq r_2$$$. This can be done using the standard technique (e-maxx.ru version has bugs). Implementation: 296834109.
TLE after systest (F).
O(Q * sqrt X * log(N * M) + NlogN + MlogM)
What's going on?
$$$O(Q \cdot \sqrt X \cdot log(N \cdot M))$$$ or just $$$O(N \cdot \sqrt N \cdot log(N))$$$ in general is a very evil time complexity, and in your case you have a very bad constant factor on top of that.
Either you have to get rid of std::map in your solution, or store answers for values of $$$X$$$.
ra[X]insert a pair{X, false}intoraifradoes not containXas key. It greatly degrades performance.Are you sure? I only insert if it contains the value in the loop
Yes, I am sure: https://en.cppreference.com/w/cpp/container/map/operator_at.
if ((rb[B - d1] && ra[A - d2]) || (rb[B - d2] && ra[A - d1]) || (rb[B + d1] && ra[A + d2]) || (rb[B + d2] && ra[A + d1]))-- here you also insert some values, if maps do not contain them.the problem F gives TLE while we use map on test 25 but gets accepted with unordered_map. I know unordered_map operations are of O(1) while map takes O(logn) but is there no case of collision in unordered_map?! I dont know much about collision but it gets hacked so i prefer using map instead of unorderd map. can anyone explain?!
Clearly no one made a test case that generates collisions, else unordered_map would be O(n) and it would easily TLE. The regular map giving TLE is because your solution is probably O(n * sqrt(n) * log(n)). What you can do to solve that is simply use a vector of size 1e5 to check if a given sum exists, and that leads you to a O(n * sqrt(n)) solution, without having to worry about hash collisions.
.
I don't know if it is your case, but usually problem setters set some test cases that make your hash functions collide a lot. Since Python's set is hashed, that is probably the case, and you should solve it with another technique / data structure.
.
Well, then it wasn't the case. I just think it is good to know that Python sets are hackable, and in some TLEs it is actually because of that.
can anyone post any binary search solution for problem E
You can check out my solution.
Can anyone tell why my code is giving TLE for question G1?
Solved it 296926821
296870648
Unsure why my submission TLEs for Problem F. I tried to implement it based on the explanation of the editorial, any tips appreciated. Thanks!
Why my code isn't correct (E) ? Thanks in advance Code
I fixed your code. Here is the 296882238. Issue is same as in link
I have a question about Problems like problem F
I think my analysis was good and found the key formula
$$$X = B - (b_i \cdot \text{SumA} + a_j \cdot \text{SumB} - a_j \cdot b_i)$$$
Also, realized that the path to the solution is to somehow manipulate these terms to make the search task easier
the problem is I have no clue how to do it, so made some random attempts then read the editorial
Are there any techniques or solving methods or whatever to get better at such a task except solving many similar problems and accumulating ideas?
I encountered problems such as this one before, so i am pretty sure you just need to gain more experience. in these problems where you simplify formulas until you can get something simpler, its all about being persistent and writing down everything and also breaking everything down. Im sure if you also just broke down B into (SumA)*(SumB) you could have gotten it, but its an experience you can learn from regardless
F is just WOW!!!
nice, got to learn new thing. But it was little bit hard, since the time complexity was also tight.
Using Map it gave TLE, but Using unordered_Map it passed.
But unordered_map can also get collision and access time can become very worse leading to TLE, but here it is not the case :) DivinePunishment
chromate00
can you please suggest me what should one ideally do in this case?
My submission using maps passed, but also barely as well. Unordered map shouldnt pass, and im surprised there isnt a hack for it, but regardless i suggest using 4 boolean vectors to be safe.
It's not always easy to hack
unordered_maps. Check https://mirror.codeforces.com/blog/entry/137306?#comment-1228509 this comment. I tried hacking it with the same test but for some reason it only took 3.3s, and I don't know exactly why. It probably has something to do with the insertion order, but I'm not too sure about this.The general situation where
unordered_mapis absolutely bad is when the range of elements is large enough and is independent of $$$n$$$. The time complexity of a single insertion or search can only be at most $$$\mathcal{O}(\sqrt{n})$$$ when the range is only $$$\mathcal{O}(n)$$$, and its constant is relatively small. Read https://mirror.codeforces.com/blog/entry/132929 for more details.in problem G1 how to check the longest path from node to it's cycle in details ?
You can copypaste some topological order algorithm (like Kahn's algorithm) to know what vertices belong to a cycle. Then, reverse the adjacency list and throw a dfs from each vertex that belongs to a cycle (just don't go to neighbors that also belong to a cycle). The largest depth any dfs reaches is the maximum distance a vertex has to a cycle.
Can you tell why my code is giving TLE for question G1? I had though same approach
Java 296825126
C++ 296869151
I know i am doing some useless work but still i guess the complexity is nearly O(n)
PS-: Solved it 296926821
for the F question, i think i have implemented what the tutorial says... i am still getting a TLE on testcase 3. can someone tell how to optimize the solution? I have attached the submission for referrence...296889036
Inside your "queries loop" (O(q)), you are building a whole set from the two vectors:
That line, by itself, has complexity O(n log n), leading to a total complexity of O(qn log n). That complexity clearly TLEs given the problem constraints.
Apologies for that oversight.. i improved that by creating a unordered map apr and bpr outside the loop, which tells if an element is present in a and b..
i am still getting TLE :((
296890768
Now, your std::accumulate call is O(n), but since you are doing it inside the O(q) loop, its complexity becomes O(q*n). Since "dela" and "delb" don't change in between queries, I think it would be a good idea to compute them outside of the "queries loop", therefore decreasing the complexity of your algorithm.
Does a wrong submission decrease rating/ranking?
During a div4 contest, each wrong submission on a problem you have successfully solved will increase your penalty time by 10 minutes
why am getting tle in problem f and my timecomplexity- q*sqrt(abs(x))*(logn +log m)
submission
Here, I explained it for you :) https://mirror.codeforces.com/blog/entry/137368
The TLE is the real demon in problem F.
2044F — Easy Demon Problem , we know that beauty of matrix is always Sum_A*Sum_B, if we make ai=0 and bj=0, beauty will be (Sum_A — ai)*(Sum_B — bj). I think it's a simpler way to think.
Whoever got "Wrong answer on test 19" on problem D like this person (https://mirror.codeforces.com/contest/2044/submission/296678418) should be banned. It's code I leaked and hacked. There are hundreds of people to ban easily.
Problem F can be translated into a "product query" problem. Given two sets of integers $$$A$$$ and $$$B$$$, check if it is possible to find $$$a \in A$$$ and $$$b \in B$$$, such that $$$a \times b = x$$$.
In the original problem, $$$x$$$ is at most $$$2 \times 10^5$$$, so you could pre-process every possible multiplication that does not exceed the upper bound in $$$XlogX$$$, where $$$X$$$ denotes the upper bound of $$$x$$$. How do you approach this problem if $$$x$$$ can be very large? Say, $$$x \leq 10^{12}$$$.
For Test case 1 of problem E, I get 7 instead of 12. Can someone please point out my mistake.
Here are the values i get for (x, y)
(2, 4) (2, 8) (3, 6) (3, 12) (4, 8) (5, 10) (6, 12)
Nvm, I did not consider the power of 0
https://mirror.codeforces.com/contest/2044/submission/321170507
why getting WA38 on F ??
you need to make ints long long and some small changes to code work faster like reserve and unordered_map 325272337