2Tree Запити#12314

2Tree Запити (Розбір)

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

Хасан Салех (MathModel)

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

Хасан Салех (MathModel)

Редаговано:

Хасан Салех (MathModel)

Рішення

У Tree, вузол має нащадків та 2u+1. Глибина — це кількість ребер, щоб досягти , тому

\mathrm{depth}(x)=\lfloor \log_2 x \rfloor.

Отже, всі вузли глибини формують інтервал

[2^y,\;2^{y+1}-1].

Нам дано та запити (a,b,c,d), і ми повинні підрахувати впорядковані пари такі, що: 1\le u\le v\le n, є предком , \mathrm{depth}(u)\in[a,b], \mathrm{depth}(v)\in[c,d].

Фіксуємо \mathrm{depth}(v)=y. Тоді має точно одного предка на кожній глибині 0,1,\dots,y, тому кількість предків з глибиною в дорівнює кількості цілих чисел в

[a,b]\cap[0,y],

що дорівнює

f(y)=\max\bigl(0,\;\min(b,y)-a+1\bigr).

Всі вузли однієї й тієї ж глибини вносять однакове , отже, відповідь на запит стає

\sum_{y=c}^{d} \mathrm{cnt}[y]\cdot f(y),

де — це кількість вузлів глибини серед .

Нехай D=\lfloor \log_2 n \rfloor буде максимальною глибиною. Для 0\le y < D рівень заповнений:

\mathrm{cnt}[y]=2^y,

а останній рівень частковий:

\mathrm{cnt}[D]=n-2^D+1.

Для кожного запиту, якщо c>D, відповідь дорівнює , і ми обмежуємо d=\min(d,D). Потім ми ітеруємо y=c..d: нехай mx=\min(b,y), якщо mx\ge a, додаємо (mx-a+1)\cdot \mathrm{cnt}[y].

Оскільки D\le 56 для n\le 10^{17}, кожен запит є , тобто близько операцій, що швидко для q\le 10^6.

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

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

    long long n; int q;
    cin>>n>>q;

    int D=63-__builtin_clzll((unsigned long long)n);

    vector<long long> cnt(D+1);
    for(int y=0;y<D;y++)cnt[y]=1LL<<y;
    cnt[D]=n-(1LL<<D)+1;

    while(q--){
        long long a,b,c,d;
        cin>>a>>b>>c>>d;

        if(c>D){cout<<0<<"\n";continue;}
        if(d>D)d=D;

        long long ans=0;
        for(long long y=c;y<=d;y++){
            long long mx=min(b,y);
            if(mx>=a)ans+=(mx-a+1)*cnt[y];
        }
        cout<<ans<<"\n";
    }
}