Хацуне Міку#11856

Хацуне Міку (Розбір)

Автор проблеми:

(De3b0o)

Підготовлено:

Hasan Saleh (MathModel)

Редаговано:

(De3b0o)

Рішення

Оскільки є дільником , тобто x \bmod k=0, ми можемо ігнорувати a_i \bmod k.

Доказ :

Припустимо, у нас є число y<x, y \bmod k = 0 і нам потрібно операцій, щоб зробити його рівним , формально

\displaystyle (y + ek = x)

Тоді для числа y+z, де 0 \le z<k (це означає, що (y+z) \bmod k = z), якщо ми виконаємо e-1 операцій, нове число буде y+z+(e-1) \cdot k < y+e \cdot k = x, тому нам все ще потрібна одна операція, щоб зробити його принаймні , ми все ще використовуємо операцій, тому a_i \bmod k не має значення.

Тепер, якщо ми оновимо кожне a_i до a_i - a_i \bmod k, всі елементи стануть кратними , тому ми можемо просто поділити все на .

Ми залишилися з k=\frac{k}{k}=1, x=\frac{x}{k} і \displaystyle a_i=\frac{(a_i - a_i \bmod k)}{k} = \left \lfloor \frac{a_i}{k} \right \rfloor.

Тепер k=1, тому набагато легше знайти відповідь на запит.

Для одного запиту:

(ми будемо посилатися на максимальну кількість одержимих фанатів як і мінімальну кількість операцій, що потрібні, як , і всі значення після оновлення, тому k=1, x=\frac{x}{k} і \displaystyle \left \lfloor \frac{a_i}{k} \right \rfloor.

Ми можемо легко побачити, що

\displaystyle \text{mx} = \min(\frac{\sum(a)}{x} , n)

Щоб знайти , ми спочатку спостерігаємо, що оптимально зробити найбільшого фаната в масиві одержимим (оскільки це вимагає менше операцій).

Серед найбільших елементів, якщо всі елементи вже більші за , тоді \text{mn} = 0.

В іншому випадку, для кожного елемента, який строго менше , ми повинні зробити його рівним .

Припустимо, є таких елементів, y_1 , y_2 , y_3 , ... , y_z.

Тоді

\displaystyle \text{mn} = \sum_{i=1}^z (x-y_i)

Якщо масив відсортований, ми можемо легко обчислити , , використовуючи префіксні суми та бінарний пошук.

Тепер нам лише потрібно спосіб підтримувати масив та префіксні суми для кожного різного .

Для одного , кількість різних значень \displaystyle \left \lfloor \frac{a_i}{k} \right \rfloor є максимум \frac{\max(a)}{k}, тому ми можемо стиснути масив до \frac{\max(a)}{k} елементів і підтримувати частоти.

Якщо ми зробимо це для кожного , складність буде максимум \mathcal{O}(\frac{A}{1} + \frac{A}{2} + \frac{A}{3} + .... + \frac{A}{A}), що є \mathcal{O}(A \log(A)), де A = \max(a).

Посилаючись на гармонічний ряд, де:

\displaystyle \int_1^n \frac{1}{x} dx = \log_e(n)

так що остаточна складність є \mathcal{O}(A \log(A) + q \log(n)), що є достатньо швидким.

#include<bits/stdc++.h>
#define ll long long
#define F first
#define S second
#define in insert
#define pb push_back
#define d3 ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define cans cout << ans << "\n";
#define yes cout << "YES" << "\n";
#define no cout << "NO" << "\n";
#define pll pair<ll,ll>
#define lin cout << "\n";
#define mid ((l+r)/2)
#define lc (2*x)
#define rc (2*x+1)
 
using namespace std;

const ll N = 1e6+9;

ll n , q;
ll a[N];
pll ans[N];
ll frq[N];
pair<pll,ll> qu[N];
ll x , k;
vector<pll> v,p;

int main()
{
    d3
    cin >> n >> q;
    for(int i = 1 ; n>=i ; i++)
        cin >> a[i],frq[a[i]]++;
    for(int i = 1 ; N>i ; i++)
        frq[i]+=frq[i-1];
    for(int i = 0 ; q>i ; i++)
    {
        cin >> x >> k;
        qu[i]={{k,x},i};
    }
    sort(qu,qu+q);
    ll pk = 0;
    ll sum;
    ll sz;
    for(int h = 0 ; q>h ; h++)
    {
        x = qu[h].F.S;
        k = qu[h].F.F;
        ll id = qu[h].S;
        if(k!=pk)
        {
            v.clear();
            p.clear();
            v.pb({-1,0});
            p.pb({0,0});
            sum=0;
            for(ll i = 0 ; N>i ; i+=k)
            {
                ll r = min((i+k),N)-1;
                ll e = frq[r];
                if(i)
                    e-=frq[i-1];
                if(e)
                    v.pb({i/k,e}),p.pb({(i/k)*e,e});
                sum+=(i/k)*e;
            }
            for(int i = 1 ; p.size()>i ; i++)
                p[i].F+=p[i-1].F,p[i].S+=p[i-1].S;
            sz=p.size();
        }
        pk=k;
        x/=k;
        ll mx = min(n,sum/x);
        if(mx==0)
        {
            ans[id]={0,0};
            continue;
        }
        ll mn = 0;
        ll l = 1 , r = sz-1;
        ll id1=sz , id2;
        while(l<=r)
        {
            if(p[sz-1].S-p[mid-1].S<=mx)
                id1=mid,r=mid-1;
            else
                l=mid+1;
        }
        l=0 , r = sz-1;
        while(l<=r)
        {
            if(v[mid].F<=x)
                id2=mid,l=mid+1;
            else
                r=mid-1;
        }
        mn = x*(p[id2].S-p[id1-1].S)-(p[id2].F - p[id1-1].F);
        ans[id].F=mx;
        mx-=(n-p[id1-1].S);
        mn += x*mx - (v[id1-1].F*mx);
        ans[id].S=mn;
    }
    for(int i = 0 ; q>i ; i++)
        cout << ans[i].F << " " << ans[i].S << "\n";
}