传送门

解题思路

  点分树其实就是在点分治的基础上,把重心连起来。这样树高是$log$的,可以套用数据结构进行操作。这道题是求最远距离,所以每个点维护两个堆,分别表示所管辖的子树的最远距离和到父节点的距离,再维护一个全局堆表示答案。修改的时候就从这个点开始暴力往上跳,每次修改到父节点的距离从而影响其父节点的子树的距离。时间复杂度$O(nlog^2n)$

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std;
const int N=100005; inline int rd(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x;
} void out(int x){
if(!x) return ;out(x/10);putchar('0'+x%10);
} inline int max(int x,int y){return x>y?x:y;} int n,head[N],cnt,to[N<<1],nxt[N<<1],Min,siz[N],m;
int dep[N],g[N][25],fa[N],Sum,rt,tot;
bool vis[N],open[N]; struct Heap{
priority_queue<int> del,Q;
inline void Push(int x) {Q.push(x);}
inline void Del(int x) {del.push(x);}
inline int Top(){
while(del.size() && Q.top()==del.top())
del.pop(),Q.pop();
return Q.top();
}
inline void Pop(){
while(del.size() && Q.top()==del.top())
del.pop(),Q.pop();
Q.pop();
}
inline int sec_Top(){
int tmp=Top(); Pop();
int ret=Top(); Push(tmp);
return ret;
}
inline int size(){return Q.size()-del.size();}
}f[N],c[N],ans; inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
} int top[N],son[N],Fa[N]; void dfs(int x,int F){
siz[x]=1; Fa[x]=F; int u,maxson=-1;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==F) continue;
dep[u]=dep[x]+1; dfs(u,x); siz[x]+=siz[u];
if(siz[u]>maxson) maxson=siz[u],son[x]=u;
}
} void dfs2(int x,int topf){
top[x]=topf;if(!son[x]) return ;
dfs2(son[x],topf);int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==Fa[x] || u==son[x]) continue;
dfs2(u,u);
}
} inline void init(){
n=rd();int x,y;
for(int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y); add(y,x);
}
dfs(1,0); dfs2(1,1);
} void dfs1(int x,int F){
siz[x]=1; int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(vis[u] || u==F) continue;
dfs1(u,x); siz[x]+=siz[u];
}
} inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]]) x=Fa[top[x]];
else y=Fa[top[y]];
}
return dep[x]<dep[y]?x:y;
} inline int DIS(int x,int y){
if(!x || !y) return 0;
int lca=LCA(x,y);
return dep[x]+dep[y]-2*dep[lca];
} void get_rt(int x,int F){
int Max=0,u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==F || vis[u]) continue;
get_rt(u,x); Max=max(Max,siz[u]);
}
Max=max(Max,Sum-siz[x]);
if(Max<Min) {Min=Max;rt=x;}
} inline void get_dis(int x,int F,int pre){
f[pre].Push(DIS(fa[pre],x));
for(int i=head[x];i;i=nxt[i]){
int u=to[i]; if(vis[u] || u==F) continue;
get_dis(u,x,pre);
}
} inline void Insert(Heap &x){
if(x.size()>1) ans.Push(x.Top()+x.sec_Top());
} inline void Erase(Heap &x){
if(x.size()>1) ans.Del(x.Top()+x.sec_Top());
} int DFS(int x,int F){
dfs1(x,0); Sum=siz[x]; Min=Sum+1; get_rt(x,0);
int G=rt,son; fa[G]=F; vis[G]=1; Sum=0;
get_dis(G,0,G); c[G].Push(0); rt=0;
for(register int i=head[G];i;i=nxt[i]){
int u=to[i]; if(vis[u]) continue;
son=DFS(u,G); c[G].Push(f[son].Top());
}
Insert(c[G]);
return G;
} inline void solve_open(int x){
Erase(c[x]); c[x].Del(0); Insert(c[x]);
for(register int y=x;fa[y];y=fa[y]){
Erase(c[fa[y]]);
c[fa[y]].Del(f[y].Top());
f[y].Del(DIS(x,fa[y]));
if(f[y].size()) c[fa[y]].Push(f[y].Top());
Insert(c[fa[y]]);
}
} inline void solve_close(int x){
Erase(c[x]); c[x].Push(0); Insert(c[x]);
for(register int y=x;fa[y];y=fa[y]){
Erase(c[fa[y]]);
if(f[y].size()) c[fa[y]].Del(f[y].Top());
f[y].Push(DIS(x,fa[y]));
c[fa[y]].Push(f[y].Top());
Insert(c[fa[y]]);
}
} inline void work(){
char c=getchar();while(c!='C' && c!='G') c=getchar();
if(c=='G') {
if(tot<=1) printf("%d\n",tot-1);
else out(ans.Top()),putchar('\n');
}
else {
int x=rd();
if(!open[x]) tot--,solve_open(x),open[x]=1;
else tot++,solve_close(x),open[x]=0;
}
} int main(){
init(); DFS(1,0); m=rd(); tot=n;
while(m--) work();
return 0;
}

最新文章

  1. 【转】使用:after清除浮动
  2. C#序列化与反序列化方式简单总结
  3. UML:时序图
  4. Android中 服务里的方法抽取成接口
  5. angularJs 页面筛选标签小功能
  6. ASP.NET-FineUI开发实践-8(二)
  7. 做了一个jquery插件,使表格的标题列可左右拉伸
  8. 自动同步Android源代码的脚本(repo sync)
  9. CentOS/RedHat rpm方式安装Apache2.2
  10. 使用类似于中介者模式实现不同VC之间的跳转
  11. RQNOJ 201 奥运大包围:LIS + 拼链成环
  12. 消息中间件选型分析——从Kafka与RabbitMQ的对比来看全局
  13. 用servlet进行用户名和密码校验
  14. java中,字符串类型的时间数据怎样转换成date类型。
  15. WPF窗体程序入口 自定义窗体启动页面
  16. 奇异值分解(SVD)与在降维中的应用
  17. 项目期复习:JS操作符,弹窗与调试,凝视,数据类型转换
  18. python slots
  19. 滑动条QSlider
  20. python操作excel及json

热门文章

  1. BZOJ 4883 棋盘上的守卫 解题报告
  2. CTF | bugku | 速度要快
  3. [CSP-S模拟测试]:序列(主席树)
  4. About Intel&#174; Processor Numbers
  5. pycharm运行html文件报404错误
  6. Oralce-PL/SQL编程-游标
  7. iOS OpenGL ES简单绘制纹理
  8. 大数据学习笔记之Hadoop(三):MapReduce&YARN
  9. Python异或加密字符串
  10. AtCoder ABC 140E Second Sum