【题目分析】

这题好基啊。

先把分治树搞出来。然后每个节点两个堆。

第一个堆保存这个块里的所有点(即分治树中的所有儿子)到分治树上的父亲的距离。

第二个堆保存分治树子树中所有儿子第一个堆的最大值。

建一个答案堆,表示所有节点第二个堆的最大值和次大值的和。

然后就是维护。

两点间距离用LCA转RMQ

调了4h,代码一度改到7k

【代码】

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxe 200005
#define maxn 100005
#define inf (0x3f3f3f3f)
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i) int h[maxe],to[maxe],ne[maxe],en=0,ban[maxn],n,m,rt,now,dst[maxn],Tree_rt,col[maxn],ans=-1,x,aim;
int b[maxn<<2],cnt=0,tag=0,pos[maxn],c[maxn<<2][20],_log[maxn<<2]; void add(int a,int b) {to[en]=b;ne[en]=h[a];h[a]=en++;}
struct Heap{
priority_queue <int> heap,del;
void Ins(int x){heap.push(x);}
void Del(int x){del.push(x);}
void Pop(){while (del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); heap.pop();}
int Top(){while (del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); return heap.top();}
int S_Top(){int tmp=Top(),ret;Pop();ret=Top();Ins(tmp);return ret; }
int Size(){return heap.size()-del.size();}
}s1[maxn],s2[maxn],lst; int mx[maxn],siz[maxn],size,fa[maxn];
char opt[11]; void dfs(int o,int fa)
{
if (!tag)b[++cnt]=o,pos[o]=cnt;
siz[o]=1;mx[o]=0;
for (int i=h[o];i>=0;i=ne[i])
if (!ban[to[i]]&&to[i]!=fa)
{
dfs(to[i],o);
if (!tag) b[++cnt]=o;
siz[o]+=siz[to[i]];
if (siz[to[i]]>mx[o]) mx[o]=siz[to[i]];
}
} void dfs_rt(int o,int fa)
{
if (max(mx[o],size-siz[o])<now) rt=o,now=max(mx[o],size-siz[o]);
for (int i=h[o];i>=0;i=ne[i])
if (!ban[to[i]]&&to[i]!=fa) dfs_rt(to[i],o);
} int lca(int a,int b)
{
int pa=pos[a],pb=pos[b];
if (pa>pb) swap(pa,pb);
int l=_log[pb-pa+1];
return min(c[pa][l],c[pb-(1<<l)+1][l]);
} int dist(int a,int b)
{return dst[a]+dst[b]-2*lca(a,b);} void dfs_add(int o,int fa)
{
s1[rt].Ins((dist(o,aim)));
for (int i=h[o];i>=0;i=ne[i])
if (!ban[to[i]]&&to[i]!=fa)
dfs_add(to[i],o);
} void Divide(int o,int fat)
{
int root;
dfs(o,-1); size=siz[o]; now=inf;
dfs_rt(o,-1); root=rt;
if (fat) fa[root]=fat;
ban[root]=1;
aim=fat;
dfs_add(root,-1);
s2[fat].Ins(s1[root].Top());
if (!col[root])
s2[root].Ins(0);
for (int i=h[root];i>=0;i=ne[i])
if (!ban[to[i]]) Divide(to[i],root);
if (s2[root].Size()>=2)
{
ans=max(ans,s2[root].Top()+s2[root].S_Top());
lst.Ins(s2[root].Top()+s2[root].S_Top());
}
} void dfs_dist(int o,int fat)
{
for (int i=h[o];i>=0;i=ne[i])
if (to[i]!=fat)
dst[to[i]]=dst[o]+1,dfs_dist(to[i],o);
} void Delete(int o)
{
if (s2[o].Size()>=2)
lst.Del(s2[o].Top()+s2[o].S_Top());
s2[o].Del(0);
if (s2[o].Size()>=2)
{
ans=max(ans,s2[o].Top()+s2[o].S_Top());
lst.Ins(s2[o].Top()+s2[o].S_Top());
}
if (s2[o].Size()>0) ans=max(ans,0);
int now=o;
while (now)
{
int fat=fa[now];
if (s2[fat].Size()>=2)
lst.Del(s2[fat].Top()+s2[fat].S_Top());
int tmp=s1[now].Top();
s1[now].Del(dist(o,fat));
if (s1[now].Size()==0||tmp!=s1[now].Top())
{
s2[fat].Del(tmp);
if (s1[now].Size()>0)
s2[fat].Ins(s1[now].Top());
}
if (s2[fat].Size()>=2)
{
ans=max(ans,s2[fat].Top()+s2[fat].S_Top());
lst.Ins(s2[fat].Top()+s2[fat].S_Top());
}
if (s2[fat].Size()>0) ans=max(ans,0);
now=fat;
}
} void Insert(int o)
{
if (s2[o].Size()>=2)
lst.Del(s2[o].Top()+s2[o].S_Top());
s2[o].Ins(0);
if (s2[o].Size()>=2)
{
ans=max(ans,s2[o].Top()+s2[o].S_Top());
lst.Ins(s2[o].Top()+s2[o].S_Top());
}
if (s2[o].Size()>0) ans=max(ans,0);
int now=o;
while (now)
{
int fat=fa[now];
if (s2[fat].Size()>=2)
lst.Del(s2[fat].Top()+s2[fat].S_Top());
int tmp,flag=0;
if (s1[now].Size()==0) flag=1;
else tmp=s1[now].Top();
s1[now].Ins(dist(o,fat));
if (flag||tmp!=s1[now].Top())
{
if (!flag)
s2[fat].Del(tmp);
s2[fat].Ins(s1[now].Top());
}
if (s2[fat].Size()>=2)
{
lst.Ins(s2[fat].Top()+s2[fat].S_Top());
ans=max(ans,s2[fat].Top()+s2[fat].S_Top());
}
if (s2[fat].Size()>0) ans=max(ans,0);
now=fat;
}
} int main()
{
memset(h,-1,sizeof h);
scanf("%d",&n);
F(i,1,n-1)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
tag=1;
dfs(1,-1);
now=inf; size=siz[1]; dfs_rt(1,-1); dfs_dist(rt,-1);
tag=0;
dfs(rt,-1);
tag=1;
F(i,1,cnt) c[i][0]=dst[b[i]]; F(i,2,cnt) _log[i]=_log[i>>1]+1;
F(j,1,_log[cnt])
for (int i=1;i+(1<<j)-1<=cnt;++i)
c[i][j]=min(c[i][j-1],c[i+(1<<j-1)][j-1]);
Tree_rt=rt;
Divide(1,0);
scanf("%d",&m);
F(i,1,m)
{
scanf("%s",opt);
switch(opt[0])
{
case 'G': if (lst.Size()) ans=max(ans,lst.Top());printf("%d\n",ans); break;
case 'C': scanf("%d",&x); ans=-1; if (!col[x]) Delete(x); else Insert(x); col[x]^=1; break;
}
}
}

  

最新文章

  1. C#中==、Equals、ReferenceEquals的区别
  2. canvas 画字
  3. 【转】win8.1下安装ubuntu
  4. Azure sdk for python
  5. Windows7给C盘扩容
  6. oracle删除用户及其名下对象
  7. C# 反射操作方法
  8. HTML5 文件API(二)
  9. Linux下vsftp服务器—上传、下载
  10. jq获取元素到底部的距离
  11. telnet 命令使用详解
  12. 最长非降子序列的O(n^2)解法
  13. 201521123024 java 第十周学习总结
  14. 2017-06-20 (pwd ls cd)
  15. JavaI/O体系详解
  16. Java基础-抽象类和接口
  17. 使用Keras训练大规模数据集
  18. loadrunner&#160;场景设计-添加Windows&#160;Resources计数器
  19. 线程同步——用户模式下线程同步——Interlocked实现线程同步
  20. MYSQL的空间查询(转帖)

热门文章

  1. cacti图形字符乱码
  2. sql中保留2位小数
  3. MySQL出现GROUP BY clause错误解决办法
  4. Jsoup获取全国地区数据(省市县镇村)(续) 纯干货分享
  5. codevs 1008 选数
  6. iPhone开发小工具
  7. Linux OpenGL 实践篇-13-geometryshader
  8. SQL——SQL语言全部关键字详解
  9. iOS,APP退到后台,获取推送成功的内容并且语音播报内容。
  10. CAD交互绘制mcdbsolid对象(网页版)