Блог пользователя ABalobanov

Автор ABalobanov, 9 месяцев назад, По-русски

Всем спасибо за участие! Надеемся, вам понравились задачи.

2176A - Операции с инверсиями

Подсказки
Решение
Имплементация

2176B - Оптимальные сдвиги

Подсказки
Решение
Имплементация

2176C - Нече(с)тный процесс

Подсказки
Решение
Имплементация

2176D - Пути Фибоначчи

В рамках этого разбора мы будем называть простые пути графа, последовательность чисел на которых образует обобщённую последовательность Фибоначчи — путями Фибоначчи.

Подсказки
Решение
Имплементация

2176E - Удалите за наименьшую стоимость

Подсказки
Решение без запросов
Подсказка 3
Решение для запросов
Имплементация

2176F - оМега числа

Подсказки
Решение
Имплементация

Разбор задач Codeforces Round 1070 (Div. 2)

Разбор задач Codeforces Round 1070 (Div. 2)
  • Проголосовать: нравится
  • +139
  • Проголосовать: не нравится

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

Автокомментарий: текст был обновлен пользователем ABalobanov (предыдущая версия, новая версия, сравнить).

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +6 Проголосовать: не нравится

Auto comment: topic has been updated by ABalobanov (previous revision, new revision, compare).

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +43 Проголосовать: не нравится

Writing first so 123gjweq2 can't say first

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится

I couldn't understand the tutorial code, so here's a (maybe) simpler top-down DP implementation with a very similar idea (compressing edge state into (end node index, start node value) pairs) for those like me. 353122473

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +12 Проголосовать: не нравится

I thought of a different solution for problem D that barely passed in time.

Observe that the value written at a certain vertex is at most $$$10^{18}$$$. Therefore, no generalized Fibonacci path is longer than $$$86$$$ nodes, as the $$$87$$$-th non-generalized Fibonacci number is greater than $$$10^{18}$$$ (and this should hold for any other larger starting numbers than both being $$$1$$$). This can easily be checked with a program that calculates the first $$$n$$$ Fibonacci numbers.

Thus, we can store for each node the amount of paths that require the next node in a path to have a certain value, which is given by the sum of the value at the node and each adjacent node entering it, calculated in the previous iteration. Initially, accounting for paths of length 2, we can store at the destination of each edge all the sums between the value of that node and any node entering it, counting possibly repeated sums.

For convenience I used the reversed graph, as that way I could just check for a each node in an iteration if its value is present at the map of sums computed in the previous iteration for each of the outgoing nodes. Though that was just a decision I made while implementing during the contest.

Due to the initial observation, there would be at most $$$87$$$ iterations over all the nodes and edges. Also, by using a map to lookup and update values present at a certain destination, I have a $$$\log$$$ factor in my solution to account for.

Hence, the complexity of this solution should be around $$$O(87 \cdot (n+m) \log m)$$$, considering in each iteration at most $$$m$$$ distinct sums would be computed (one for each edge), amounting to around $$$6.5 \cdot 10^8$$$ operations (explaining why my solution barely passed the TL). Also, I may be off in the exact numbers, but the general idea is that "Fibonnaci paths are short".

Here's my submission: 353082932

  • »
    »
    9 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +1 Проголосовать: не нравится

    I tried to make use of the same idea (paths have length at most $$$87$$$) in some of my initial submissions but got TLE. After that, I realised I can just sort the vertices by $$$a_i$$$ and compute the DP in that order, so I very quickly modified the code to make it pass. Even the for-loop over the lengths is still in there!

    • »
      »
      »
      9 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Yup, after reading the editorial I got the idea of sorting edges by value in their destination, and I modified the submission I posted above. It passed in just 0.2s. The code is identical apart from that: 353380486

      While in contest I also got a TLE, so I changed to a newer compiler, optimized access to maps a bit to avoid sometimes accessing two times unnecessarily, and crossed my fingers haha. Glad I got a bit lucky.

      Nevertheless, I thought the idea was neat and worth mentioning.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +14 Проголосовать: не нравится

Here is my two pass greedy linkedlist solution for E:

https://codeforces.me/contest/2176/submission/353120120

O(Nlog(N)) because of an initial sort, otherwise O(N).

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Can anyone help me in question D?whats wrong in my approach

https://codeforces.me/contest/2176/submission/353126337

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

can anyone help me with problem D?

https://codeforces.me/contest/2176/submission/353126337

whats wrong here?intuitively seems perfect but getting wa on test 1 itself

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Why my code fail on C.

#include <bits/stdc++.h>

#define int long long

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int t, n;
ll res[N];

signed main() {
    cin >> t;
    while (t -- ) {
        vector<ll> odd, even;

        cin >> n;
        for (int i = 1; i <= n; ++ i) {
            int x;
            cin >> x;
            if (x & 1) odd.push_back(x);
            else even.push_back(x);
        }

        sort(even.begin(), even.end(), [](int x, int y) {
            return x > y;
        });
        sort(odd.begin(), odd.end(), [](int x, int y) {
            return x > y;
        });

        int l1 = even.size(), l2 = odd.size();
        if (!l2) {
            for (int i = 1; i <= n; ++ i)
                cout << 0 << " " ;
            puts("");
            continue;
        }
        memset(res, 0, sizeof res);
        res[1] = odd[0];
        for (int i = 0; i < l1; ++ i) res[i + 2] = res[i + 1] + even[i];
        // 偶数用完了 
        if (l2 & 1) {
            for (int i = l1 + 2; i <= n; ++ i)
                res[i] = res[i - 2];
        } else res[n] = 0;

        for (int i = 1; i <= n; ++ i)
            cout << res[i] << " " ;
        puts("");
    }

    return 0;
}
»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

I have a slightly different approach to D. I simply used DFS and memoization to find the answer. Since using map would give MLE (353062066), I used unordered map with custom hash function (353064160), which reduced the memory by a lot.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

Here is my solution to Problem D: Due to the rapid growth rate of Fibonacci, we can use DFS to calculate each Fibonacci number brute-force, and incorporate memoization to solve this problem. 353130807

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

having hints before main solution is really helpful, thanks

»
9 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится +2 Проголосовать: не нравится

Convolution solution to F:

alt solution >:)
»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

In problem C, what is m?

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится -8 Проголосовать: не нравится

Can someone tell why my code is giving wrong answer on test case 2 or give a test case where my code fails

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
using ll = long long;
void solve(){
    ll n;
    cin>>n;
    vector<ll>a(n);
    vector<ll>odd;
    vector<ll>even;
    for(ll i=0;i<n;i++){
        cin>>a[i];
        if(a[i]%2==0)
            even.push_back(a[i]);
        else
            odd.push_back(a[i]);
    }
    sort(odd.begin(),odd.end(),greater<ll>());
    sort(even.begin(),even.end(),greater<ll>());
    vector<ll>prefixsum(even.size()+1,0);
    for(ll i=1;i<even.size()+1;i++){
        prefixsum[i]=prefixsum[i-1]+even[i-1];
    }
    ll s = even.size()+1;
    vector<ll>val(n+1);
    for(ll k=1;k<=min(n,s);k++){
           val[k] = odd.empty() ? 0 : odd[0] + prefixsum[k-1];
    }
    for(ll k=s+1;k<=n;k+=2){
        if(even.size()==1)
            val[k]=0;
        else{
            if(s - 1 >= 1)
                val[k] = val[s - 1];
            else 
                val[k] = 0;
        }
    }
    for(ll k=s+2;k<=n;k+=2){ 
            val[k] = val[s];
    }
    if(odd.size()%2==0 && even.size()%2==0)
        val[n]=0;
    for(ll i=1;i<=n;i++){
        cout<<val[i]<<" ";
    }
    cout<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

E can be solved using segment tree beats.

For each i find l,r which is the widest range (including i) that have values <=a[i] (using stack). Then update the cost for removing each element in range l to r by assigning it to min(cost[j],c[i]) for which we use segtree beats. Initial answer would be sum of cost for all minus cost for last remaining element (which is minimum of c[j] where a[j]==max(a)). For zeroing operations, you use l,r of that element and update cost[j] to min(cost[j],0) and again find the sum of all costs. Once you have zeroed any index such that a[i]==max(a) all further costs will be 0.

This solution can be used to solve for a type of updation query where you reduce c for any element.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Finally Green Again.

»
9 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится -22 Проголосовать: не нравится

can anyone tell me, what is the error in this code ~~~~~ // this is code

include<bits/stdc++.h>

using namespace std; typedef long long ll; int main() { ll t,n,i,odd,even,sum,k,check; cin>>t; while(t--) { cin>>n; ll array[n]; odd=0,even=0; vectorodds,evens; for(i=0;i<n;i++) { cin>>array[i]; if(array[i]%2==1) { odd++; odds.push_back(array[i]); } else { even++; evens.push_back(array[i]); } } sort(odds.begin(),odds.end(),greater()); sort(evens.begin(),evens.end(),greater()); vectorpresum; sum=0; for(i=0;i<evens.size();i++) { sum+=evens[i]; presum.push_back(sum); } if(odd==0) { for(i=1;i<=n;i++) cout<<0<<" "; cout<<endl; } else if(even==0) { for(i=1;i<=n;i++) { if(i%2==1) cout<<odds[0]<<" "; else cout<<0<<" "; } cout<<endl; } else { if(odd==1) { cout<<odds[0]<<" "; for(i=0;i<presum.size();i++) cout<<odds[0]+presum[i]<<" "; cout<<endl; } else if(odd==2) { cout<<odds[0]<<" "; for(i=0;i<presum.size();i++) cout<<odds[0]+presum[i]<<" "; cout<<0<<" "<<endl; } else {// odds>=3 cout<<odds[0]<<" "; for(i=0;i<presum.size();i++) cout<<odds[0]+presum[i]<<" "; k=1+presum.size(); check=(k%2); for(i=k+1;i<=n;i++) { if((i%2)==check) cout<<odds[0]+presum[presum.size()-1]<<" "; else cout<<odds[0]+presum[presum.size()-2]<<" "; } cout<<endl; } } } return 0; } ~~~~~

»
9 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится +1 Проголосовать: не нравится

A nice observation can make code for C easier. Here is my submission 353059457 Following the nomenclature in tutorial since for k=m+2 we are using oc and all even except mth therefore it is same for k=m and again for k=m+3 it is same as k=m+1 and so on. All edge cases considered separately — All odd, no odd and even no.of odds.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

The hints of problem c are very good.

I like it how he explain all the cases in problem c.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I saw 998345353 at F when I was using a translate plugin. Who proposed the idea? Great!

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +19 Проголосовать: не нравится

For E there is a O(n) solution, you do cartesian tree and color the subtree of a node each time, with ascending c[i]'s. The only caveat is if a[node] == a[par[node]] you should start coloring from par[node] so for that I hold a link array which gets us to the highest node with the same value as the current one. Here is my solution : https://codeforces.me/contest/2176/submission/353155958

note : I did the sorting with std::sort for convenience but you can do that with counting sort to get true O(n)

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

In Problem D, why we should sort the edges by $$$a_u+a_v$$$?

  • »
    »
    9 месяцев назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится 0 Проголосовать: не нравится

    if you have a simple path and it follows the definition of fibonacci sequence, and without loss of generality lets assume if edge (u1,v1) comes before edge (u2, v2) then its sum should also be in the same order.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I spent quite a bit of time on Problem B, only to see a three-line solution in the editorial…

For reference, this is the method I used:

  • Find the shortest consecutive zero segment (length = d).
  • Shift the string by d and do a bitwise OR with the original.
  • Repeat until there are no zeros left.

Here’s my submission:B — Optimal Shifts

Can anyone confirm if this actually minimizes the number of operations (not the cost)? Would feel better knowing I wasn’t overcomplicating things.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

It turns out there is no need for 87 or 90 bound needed in problem $$$D$$$. The problem doesn't guarantees that the given graph is DAG , but we can still make it a DAG. Note that the sequence is increasing except for the first two elements. Hence make a second graph , which has an edge from $$$u$$$ to $$$v$$$ iff $$$a[v] \gt a[u]$$$. You can look at my submission 353070891

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

why is my solution failing in problem D

my code : 353225582

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

For C I think you it doesn't matter which odd number it is, except for the maximum. If at least one odd exists, you could first print the maximum odd number and then m more numbers where the ith number will be maxOdd+ith even number (in descending order) and then for the remaining numbers: m+2 to n, for jth number if (j-m) is odd print the (sum of all even+maxOdd) else print 0, and add check that if there are even number of odd numbers then nth number will be 0 regardless of the parity of j-m.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

353291565

I am getting TLE , please help in problem D

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Nice editorial for F.

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

In problem C, cnteven is for what??

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

What is the "A well-known method can be used to count the number of pairs of numbers in the array (i,j) for which gcd(ai,aj)=g for any number g from 1 to maxA" in F. Can someone say how I can google it or provide a link to editorial of this method?

  • »
    »
    9 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +4 Проголосовать: не нравится

    Well, I think I understood what method was mentioned here. In short, this is a regular dp, where we count the number of pairs that x divides, and then subtract all the other gcds that x divides. This can be done as in sieve of Eratosthenes, and it will work for O(nlogn)

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

Easy solution for D: Let's replace each edge v->u with an edge between two FAKE vertices: (v << 64 | Y) -> (u << 64 | X + Y), where X is the value associated with vertex v, and Y with u. This way, we obtain a new graph in which ANY path corresponds to a Fibonacci path! Simply count the number of paths in this graph using DFS and caching. https://codeforces.me/contest/2176/submission/353494951

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Can you guys tell me why my D is TLEing?

#include <bits/stdc++.h>
using namespace std;

/* #define int long long */

const int MOD = 998244353;
int madd(int a, int b) {
    a %= MOD;
    b %= MOD;

    return (a + b) % MOD;
}

int32_t main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt;
    cin >> tt;

    while(tt--) {
        int n, m;
        cin >> n >> m;
        vector<long long> a(n);
        for(int i = 0; i < n; ++i) {
            cin >> a[i];
        }

        //dp[i] = number of fibonacci sequences ending in edge i inclusive
        vector<int> dp(m, 1);
        vector<pair<int, int>> e;

        auto cmp = [a](pair<int, int> pa, pair<int, int> pb) {
            return a[pa.second] < a[pb.second];
        };

        for(int i = 0; i < m; ++i) {
            int u, v;
            cin >> u >> v;

            u--;
            v--;
            e.push_back({u, v});
        }

        vector<map<int, long long>> buffer(n);

        sort(e.begin(), e.end(), cmp);

        for(int i = 0; i < m; ++i) {
            auto [u, v] = e[i];
            long long sum = a[u] + a[v];

            dp[i] = madd(dp[i], buffer[u][a[v]]);
            buffer[v][sum] = madd(buffer[v][sum], dp[i]);
        }

        int ans = 0;
        for(int x: dp) {
            ans = madd(ans, x);
        }
        cout << ans << '\n';
    }
}

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

PROBLEM D: I am getting TLE on test case 11 353509271. What can I do better?

»
9 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

For F, a slightly better bound on K can be given. The primorial function is bigger than n! so it's inverse is less. By Stirling, n! is $$$O\left(e^{n \ln(n)}\right)$$$ and the inverse of this is $$$O\left(\log(n)/\log(\log(n))\right)$$$

»
9 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится +8 Проголосовать: не нравится

I've found, I guess, very simple linear solution to problem E.

Let's see that an element can be killed only by first not-less element on the right|left, or first not-less than first not-less on the right|left, or ...

We will denote the set of elements, which are able to kill element at position $$$i$$$, as $$$killers(i)$$$.

Let's assign for each $$$i$$$ the cheapest element from $$$killers(i)$$$ to kill $$$i$$$.

The observation: there is a sequence of deletions which satisfies our assignments.

The proof's sketch: Let's draw an arrow from each position i to his killer. It suffices to show that there are no crossing arrows. We can see that if two arrows are crossing, then we can reassign one of them and obtain cheaper solution.

It is known that we can compute "first not-less on right|left" in linear time. With a simple DP we can also compute those assignments in $$$O(n)$$$. The answer is just a sum of costs of killing each element. So we solved E without queries.

We can now observe that any changes in elements that doesn't belong to $$$killers(i)$$$ don't have any impact on the cost of killing $$$i$$$. Hence it suffices to compute, for each element, the first time that some member of $$$killers(i)$$$ is changed to zero. We can solve it in $$$O(n)$$$ with very similar DP.

»
8 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I thought of a different solution for problem C .

The approach is to separate the numbers into even and odd and sort even numbers in descending order and odd numbers in descending order. If there are no odd numbers then the answer would be zero for all k. If there are no even numbers then the answer would be zero for even k and the largest odd number for odd k. We need the sum of even numbers to reduce the O(n) complexity to calculate again, so prefix sums of even numbers are used. For each k, first start by placing the largest odd number. If the number of evens available are enough then just add the number of even numbers required in descending order. If the number of even numbers available are less than required, then if the number of odd numbers to be used are even, simply place them before the largest odd number as their sum would give 0, so the answer should be the largest odd number plus the sum of all even numbers. If the number of odd numbers to be used are odd, then simply remove the smallest even number and place all odd numbers available before the largest odd number, and if k equals n (that is all numbers are to be used) then the sum would be 0.

Here is my submission :

https://codeforces.me/contest/2176/submission/356942161

»
8 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Problem C. Odd Process

Can anybody explain sample cases 3 and 4?

Input:

5
4 1 3 1 2
5
4 2 3 1 3

Output:

3 7 9 7 9
3 7 9 7 9

In sample 3, for example, on $$$k=4$$$, doesn't the bag contain $$$[3, 4, 2, 1]$$$, with the even sum $$$10$$$, therefore being emptied and giving a score of $$$0$$$? How is the score $$$7$$$ instead? Same confusion with sample 4.

»
8 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

4

»
8 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

A Better Approach for Problem C 2176C - ODD PROCESS - Odd Process LYC_666 ~~~~~ #include<bits/stdc++.h> using namespace std;

define int long long

bool cmp(int t1,int t2) { return t1 > t2; }

signed main() { ios::sync_with_stdio(0), cin.tie(0); int t; cin >> t; while (t--) { int n; cin >> n; vectorodd, even; for (int i = 0; i < n; i++) { int v; cin >> v; if (v % 2 == 0) { even.push_back(v); } else { odd.push_back(v); } } if (odd.empty()) { for (int i = 0; i < n; i++) { cout << "0 "; } cout << "\n"; continue; } sort(even.begin(), even.end(),cmp), sort(odd.begin(), odd.end(), cmp); int size = even.size() + 1; vectorpre(size + 1); pre[1] = odd[0]; for (int i = 0; i < even.size(); i++) { pre[i + 2] = pre[i + 1] + even[i]; } for (int i = 1; i < n; i++) { if (i <= size) { cout << pre[i]<<" "; } else { if ((i — size) % 2 == 1) { cout << pre[size — 1] << " "; } else { cout << pre[size] << " "; } } } if (odd.size() % 2 == 0) { cout << "0"; } else { cout << pre[size]; } cout << "\n"; } return 0; } ~~~~~

»
6 недель назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

B can be solved using simple BFS 386692869