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

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

1795A - Две башни

Идея: BledDest

Разбор
Решение (Neon) 1
Решение (Neon) 2

1795B - Идеальная точка

Идея: BledDest

Разбор
Решение (Neon)

1795C - Дегустация чая

Идея: BledDest

Разбор
Решение (Neon)

1795D - Раскраска треугольников

Идея: BledDest

Разбор
Решение (BledDest)

1795E - Взрывы?

Идея: BledDest

Разбор
Решение (adedalic)

1795F - Блокирующие фишки

Идея: BledDest

Разбор
Решение (awoo)

1795G - Последовательные удаления

Идея: BledDest

Разбор
Решение (awoo)
  • Проголосовать: нравится
  • +121
  • Проголосовать: не нравится

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

Copy paste error in tutorial for F

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

I found problem C difficult in this round.

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

I try problem C using segment tree and got AC.

here is the idea:

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

    that's just unnecessarily complicated tho

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

      Not really.

      If you need to update and query a range, segment tree is intuitive. Adding a number and querying the sum in a range has is one the most common forms of segment trees. Also, you don't need to type a segment tree. It's just a copy-paste.

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

My approach for problem C

void solve()
{
    ll n, x;
    cin >> n;
    ll a[n];
    for (ll i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    multiset<ll> s;
    ll val = 0;
    for (ll i = 0; i < n; i++)
    {
        cin >> x;
        ll mn = min(x, a[i]), c = 0;
        s.insert(a[i] + val);
        auto it = s.begin();
        vector<ll> toBeRemoved;
        while (1)
        {
            if (it == s.end())
                break;
            if (*it - val <= x)
            {
                c += *it - val;
                toBeRemoved.push_back(*it);
            }
            else
            {
                break;
            }
            it++;
        }
        for (auto e : toBeRemoved)
            s.erase(e);
        val += x;
        c += s.size() * x;
        // c += mn;
        a[i] -= mn;
        cout << c << " ";
    }
    cout << "\n";
}
  • »
    »
    22 месяца назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    The time complexity is O(n^2) right? It's accepted?

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

      It's O(Nlog(N))

      for (auto e : toBeRemoved)
                  s.erase(e);
      

      erase takes O(logN) at the worst case (erase all elements that became 0)

      c += s.size() * x; take the value x from all elements in the set that will not become zero after we take x (greater than x)

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

    please explain your approach

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

      The array "a" stores some values ** consider a[0] this value will be reduced by all values in b -> b[0:n[ a[1] will be reduced by all values in b -> b[1:n[

      consider b[1] b[1] will reduce values in a[1] and a[0]

      so when you take b[i] which is x in my solution add it to variable "val" which store sum of values of b until i (I'm sure that val will reduce all previous "a" values with its value) so for each element in the set, when an element becomes zero that's mean I can't reduce it any more so I should remove it from the set but other elements in the set that when I reduce it by x, It won't be zero (c+= x*size). I'm very bad at explanation so if you don't understand tell me.

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

BledDest i guess, there is a typo in a problem C editorial

" Now you want to find the largest j such that pref[ j-1 ]−pref[ i ] ≤ a[ i ]. Rewrite it as pref[ j-1 ] ≤ a[ i ] + pref[ i ] "

it should be pref[ j ] not pref[ j-1 ] because here pref[ j ] = b[ 0 ] + b[ 1 ] + b[ 2 ].......b[ j-1 ] any comment ?

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

I got enlightenment guys,
the technique which is know as difference array technique by commoners has actually a fancy name : DELTA ENCODING

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

Is there any better solution in problem G?

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

maybe the difficulty gap between D&E was bigger than before (, that's probably because C was difficult and D was easier than usual .

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

G's compression trick is truly beautiful. Still I wonder is a n*n bool matrix works too?(Once I test it out I'll post the result below this comment)

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

In tutorial of E, why would the explosion series stop when $$$h_{p - i} \le h_{p} - i$$$ Doesn't this mean the explosion can proceed more left?

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

Can someone help to explain why the answer is n*(n+1)/2 — reachable pairs in problem G?

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

For G, Java don't have the function __builtin_popcountll and the same algorithm gets TLE at case 22(I compared the code with mine and the main parts are essentialy the same). Is there a java code that got accepted? Or should I just throw Java into a trash can and start using c++? And here's the code which got TLE at case 22. I even improved the edges iteration parts QAQ 194239334

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

    Computing the number of bits set to 1 naively is too slow. Here are some ways to improve it if your language of choice doesn't support that function:

    • precalculate the number of bits set to 1 in all integers up to some number $$$2^k-1$$$. Let's say that $$$k = 16$$$. Then you can calculate the number of bits set to 1 in a 64-bit number in much fewer actions if you divide the number into blocks of $$$k$$$ bits (for $$$k = 16$$$, you need only $$$4$$$ blocks).
    • use something like a bitset (although if you use it, it might be better to deal with larger number of bits, not 64).
»
22 месяца назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

In the 9th paragraph of the tutorial of E, shouldn't this be corrected like this?

The last question is finding for each i the closest j<i such that aj−i aj−j ≤ ai−i. Note that...

Correct me if I am wrong.

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

C is a good problem for practising Segment Tree.

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

IN PROBLEM D: can anyone say why we are not considering pairing a triple with same color? Because "So, for each triple of vertices, there will be either one red vertex and two blue ones, or two red ones and one blue" from editorial. or why can't BBB RRB RRB RRB give maximum weight for sure in any case??

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

    because then maximum weight will not be considered if we take all blue. read problem carefully

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

My solution for problem C using Priority Queues. I myself don't know how I came up with that!

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner ab = new Scanner(System.in);
        int T = ab.nextInt();
        while (T-- > 0) {
            int N = ab.nextInt();
            long[] tea = new long[N];
            for(int i=0; i<N; i++) tea[i] = ab.nextInt();
            long[] cap = new long[N];
            for(int i=0; i<N; i++) cap[i] = ab.nextInt();

            PriorityQueue<Long> pq = new PriorityQueue<>();
            long bal = 0;
            for(int i=0; i<N; i++) {
                long ans = 0;
                while(!pq.isEmpty()) {
                    long avl = pq.peek() - bal;
                    if(avl > cap[i]) {
                        ans += (cap[i]*pq.size());
                        break;
                    } else ans += (pq.poll() - bal);
                }
                ans += Math.min(tea[i], cap[i]);
                bal += cap[i];
                if(tea[i] > cap[i]) pq.offer(tea[i] - cap[i] + bal);

                System.out.print(ans + " ");
            }

            System.out.println();
            
        }
    }
}