找回密码
 立即注册
首页 业界区 业界 洛谷 P11345 [KTSC 2023 R2] 基地简化 题解

洛谷 P11345 [KTSC 2023 R2] 基地简化 题解

袁可佳 21 小时前
校内模拟赛题,倒在了正解前最后一步 qwq。
解题思路

首先,发现题目要求的东西很不好做。于是转化一下,考虑计算每条边对答案贡献了几次。
这样问题就转化成了求有多少个区间的点分布在一条边两端的两个子树中。
发现这个东西还是不好求。于是正难则反,考虑计算区间的点全部在同一个子树里的区间数量。
显然,这个数量可以通过 set 维护子树内外点的编号所形成的连续段实现。但实现起来细节较多,需要注意各种边界问题。
如果暴力地对每棵子树都把节点挨个 insert 一下去算这个东西,复杂度就是 \(O(n^2 \log n)\) 的,会直接 T 飞。
我们使用树上启发式合并优化这个过程。时间复杂度 \(O(n \log^2 n)\)。
Code

[code]#include #define rep(i,a,b) for(int i(a);ise;        if(lfi;        if(l==r){            (tot-=calc(l-lm-1))%=P;            (tot-=calc(rm-r-1))%=P;            (tot-=calc(1))%=P;            (tot+=calc(rm-lm-1))%=P;            s.erase(it);            return;        }        if(l==x){            (tot-=calc(r-l+1))%=P;            (tot-=calc(l-lm-1))%=P;            (tot+=calc(r-l))%=P;            (tot+=calc(l-lm))%=P;            s.erase(it);            s.emplace(l+1,r);            return;        }        if(r==x){            (tot-=calc(r-l+1))%=P;            (tot-=calc(rm-r-1))%=P;            (tot+=calc(r-l))%=P;            (tot+=calc(rm-r))%=P;            s.erase(it);            s.emplace(l,r-1);        }    }}st;void add(int l,int r){    rept(i,l,r){        st.insert(rk);    }}void dfs(int u,int pre){    l=++tim,rk[l]=u,siz=1;    for(auto [v,w]:g){        if(v==pre) continue;        up[v]=w;        dfs(v,u);        siz+=siz[v];        if(siz[ch]

相关推荐

您需要登录后才可以回帖 登录 | 立即注册