#c #algorithm #data-structures #tree #depth-first-search
#c #алгоритм #структуры данных #дерево #поиск в глубину
Вопрос:
Я пытался решить вопрос о cses — Разные цвета, мое решение основано на книге «Справочник конкурентоспособного программиста» Антти Лааксонена номер страницы 170 (Объединение структур данных)
#include<bits/stdc .h>
using namespace std;
const int Mxn = 2e5;
unordered_set<int> adj[Mxn],mp[Mxn];
int c[Mxn],ans[Mxn],n;
void dfs(int u=0, int p = -1){
for(auto v: adj[u]){
if(v != p){
dfs(v,u);
if(mp[v].size() > mp[u].size())
swap(mp[v],mp[u]);
mp[u].insert(mp[v].begin(),mp[v].end());
}
}
mp[u].insert(c[u]);
ans[u] = mp[u].size();
}
int main(){
cin>>n;
for(int i=0;i<n;i ) cin>>c[i];
for(int i=1;i<n;i ){
int x,y; cin>>x>>y; x--,y--;
adj[x].insert(y);
adj[y].insert(x);
}
dfs();
for(int i=0;i<n;i ) cout<<ans[i]<<' ';
}
Что я хочу знать, так это то, что когда я меняю местами две карты в приведенном выше коде, используя
if(mp[v].size() > mp[u].size())
swap(mp[v],mp[u]);
Код принимается, но когда я не меняю местами эти карты, я получаю TLE, вот цитата из книги :
Объединение узлов может быть выполнено следующим образом: мы проходим через дочерние элементы s и в каждом дочернем элементе u объединяем d [s] и d[u] . Мы всегда копируем содержимое из d [u] в d [s] . Однако перед этим мы поменяем местами содержимое d [s] и d[u], если d[s] меньше, чем d [u] . При этом каждое значение копируется только O (log (n)) раз во время обхода дерева, что гарантирует эффективность алгоритма.
как замена карт в соответствии с их размером гарантирует, что каждый элемент будет скопирован не более O (log (N)) раз?
Если все цвета уникальны, то сложность копирования одной карты в другую будет O (N), верно? Это сделало бы общую сложность O (N ^ 2).
Ответ №1:
Я почти уверен, что этот алгоритм известен как «слияние малого и большого». Основная идея заключается в том, что каждая вершина будет объединена в большинстве log(N)
случаев.
Во-первых, условие подкачки гарантирует, что меньший набор будет объединен с большим набором. Таким образом, каждый раз, когда какая-либо вершина v
объединяется, новый набор, содержащий v
, будет по крайней мере в два раза превышать размер исходного набора, содержащего v
. Мы можем представить, что размер наборов, содержащихся v
после каждого слияния, будет выглядеть примерно так: 1 -> 2 -> 4 -> 8 ... -> N
.
Поскольку каждая вершина будет объединена в большинстве log(N)
случаев, количество слияний для всех вершин равно N log(N)
. Конечная сложность заключается O(N log N)
в следующем .