【题解】P8968 路径压缩 思维 数据结构
因为这里是 1C 的题解不是 2C 的题解,所以就不在叙述博弈的策略与方法了,继续摆出 1C 的结论: 一直向树的上方跳,令目前的答案为
考虑使用数据结构优化这个过程。
O(n\log n\log |V|)
将
dfs 整棵树的时候用数据结构维护这个操作序列:
跳
倍增时很多路径段本身是整体的 ,但是被拆成了很多个路径段,每个路径都被拆成了
最初每个点的父亲是自己,如果它一定不会触发父亲的翻倍就把它和父亲压缩到一起,这样每一步都会跳到某段较长的一定不会触发翻倍的段的顶端。
具体实现:
对于每个点维护这个不触发倍增较长段的阈值
每经过一个这样的段,
部分代码:
struct element {
int limit , addtion , target ;
};
vector< element > Q ;
void dfs(int x) {
if(!x) return ;
int p = (int) Q.size( ) - 1 ;
ans[x] = siz[x] ;
int cnt = 0 ;
while(p > 0) {
auto [limit,addtion,target] = Q[p] ;
++cnt ;
if(ans[x] >= limit) {
ans[x] += addtion ;
p = target ;
continue;
}
ans[x] <<= 1;
p -- ;
}
if(son[x][0])
{
if(son[x][1]) {
auto nw = (element) {siz[son[x][1]],siz[son[x][1]],(int) Q.size( ) - 1} ;
while(nw.limit+nw.addtion >= Q[nw.target].limit) nw.addtion += Q[nw.target].addtion , nw.target = Q[nw.target].target ;
Q.push_back(nw);
}
dfs(son[x][0]) ;
if(son[x][1]) Q.pop_back ( ) ;
}
if(son[x][1]) {
if(son[x][0]) {
auto nw = (element) {siz[son[x][0]],siz[son[x][0]],(int) Q.size( ) - 1} ;
while(nw.limit+nw.addtion >= Q[nw.target].limit) nw.addtion += Q[nw.target].addtion , nw.target = Q[nw.target].target ;
Q.push_back(nw);
}
dfs(son[x][1]) ;
if(son[x][0]) Q.pop_back ( ) ;
}
}
于 1 月 25 日排在最优解第二。
完整代码
收录于《超级无敌神仙炫酷无敌原神大王好题》 。