首先要知道点分治和点分树(大家应该都懂的)

点分树的高度是log的,并且每一层的子树大小一定小于等于父亲的子树大小的1/2

所以我们可以对点分树上的每个点维护一些数据结构(如:线段树,堆,平衡树……)

说着简单写着难(hlq07没事写一发普通平衡树,ljh没事写一发紫荆花之恋,Freopen没事写一发希望,时代在进步)

可能就我觉得难。。。

(其实动态点分治的思想有点像树链剖分,但是它们的运用范围有大不相同)

详细代码实现见下

 

例题

捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。

Input

  第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。

Output

  对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。

Sample Input

8 1 2 2 3 3 4 3 5 3 6 6 7 6 8 7 G C 1 G C 2 G C 1 G

Sample Output

4 3 3 4

Hint

 

对于100%的数据, N ≤100000, M ≤500000。

 

 

 

题解

我的思路就是点分树上每个节点维护一棵线段树

如果当前的点由暗变亮,就对它到点分树根节点的路径上的每一棵线段树都删除它的贡献

否则就对这些线段树加上它的贡献

(注意,它对每个线段树的贡献是它到该线段树对应节点的距离)

查询就从任意一个暗的点开始向上跳父亲,在去除自己方向上的子树的贡献(注意,不是自己方向上的节点点分树)后查询最大值。找到最远点之后,再这样做一次,就可以找到最远点对(原理就跟树的直径差不多吧)

实现上有很多细节

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
inline int gi()
{
	char c;int num=0;
	while((c=getchar())<'0'||c>'9');
	while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
	return num;
}
#define N 100005
#define LOG 16
#define lc a[i].lch
#define rc a[i].rch
const int INF=0x3f3f3f3f;
int fir[N],to[2*N],nxt[2*N],cnt;
bool sta[N];int con;//record the number of dark rooms
struct ansnode{
	int mx,pos;
	ansnode(){}
	ansnode(int x,int y){mx=x;pos=y;}
	bool operator < (const ansnode &t)const{return mx<t.mx||(mx==t.mx&&pos>t.pos);}
};
struct node{int l,r,lch,rch;ansnode x;}a[N*LOG*4];
int T[N],tot;
int tmpsiz[N],nrt,all;bool vis[N];
int dis[LOG+2][N],dfn[LOG+2][N],siz[LOG+2][N],fro[LOG+2][N],dc,dfa[N],dep[N];
int tmpval[N],tmpid[N];
set<int> S;
void adde(int a,int b)
{
	to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;
	to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;
}
void build(int &i,int l,int r)
{
	if(!i)i=++tot,a[i].l=l,a[i].r=r;
	if(l==r){a[i].x.mx=tmpval[l];a[i].x.pos=tmpid[l];return;}
	int mid=(l+r)>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	a[i].x=max(a[lc].x,a[rc].x);
}
void insert(int i,int x,int k)
{
	if(x<a[i].l||x>a[i].r)return;
	if(x==a[i].l&&x==a[i].r){a[i].x.mx+=k;return;}
	insert(lc,x,k);insert(rc,x,k);
	a[i].x=max(a[lc].x,a[rc].x);
}
ansnode query(int i,int l,int r)
{
	if(a[i].l>r||a[i].r<l)return ansnode(-INF,INF);
	if(l<=a[i].l&&a[i].r<=r) return a[i].x;
	return max(query(lc,l,r),query(rc,l,r));
}
void findrt(int u,int ff)
{
	int mx=0;tmpsiz[u]=1;;
	for(int v,p=fir[u];p;p=nxt[p]){
		if(!vis[v=to[p]]&&v!=ff){
			findrt(v,u);
			tmpsiz[u]+=tmpsiz[v];
			mx=max(mx,tmpsiz[v]);
		}
	}
	mx=max(mx,all-tmpsiz[u]);
	if(mx<=(all>>1))nrt=u;
}
int getrt(int u,int sz)
{
	nrt=-INF;all=sz;
	findrt(u,0);return nrt;
}
void pre(int u,int ff,int o,int d)
{
	fro[d][u]=o;
	dfn[d][u]=++dc;siz[d][u]=1;
	tmpval[dc]=dis[d][u];tmpid[dc]=u;
	for(int v,p=fir[u];p;p=nxt[p]){
		if(!vis[v=to[p]]&&v!=ff){
			dis[d][v]=dis[d][u]+1;
			if(!o)pre(v,u,v,d);
			else pre(v,u,o,d);
			siz[d][u]+=siz[d][v];
		}
	}
}
void DFZ(int u,int d)
{
	vis[u]=1;dep[u]=d;
	dc=0;dis[d][u]=0;pre(u,0,0,d);
	if(siz[d][u]>1)build(T[u],2,siz[d][u]);
	for(int v,p=fir[u];p;p=nxt[p]){
		if(!vis[v=to[p]]){
			dfa[v=getrt(v,siz[d][v])]=u;// siz[d][v]
			DFZ(v,d+1);
		}
	}
}
ansnode getfarest(int u)
{
	int t;ansnode ans=ansnode(-INF,INF),tans;
	if(T[u])ans=query(T[u],2,siz[dep[u]][u]);
	for(t=dfa[u];t;t=dfa[t]){
		tans=max(query(T[t],2,dfn[dep[t]][fro[dep[t]][u]]-1),query(T[t],dfn[dep[t]][fro[dep[t]][u]]+siz[dep[t]][fro[dep[t]][u]],siz[dep[t]][t]));//
		if(tans.mx>=1)tans.mx+=dis[dep[t]][u];
		ans=max(ans,tans);
		if(!sta[t])ans=max(ans,ansnode(dis[dep[t]][u],t));
	}
	return ans;
}
char op[3];
int main()
{
	int n,m,i,u,v,t;
	n=gi();con=n;S.insert(n);
	for(i=1;i<n;i++){u=gi();v=gi();adde(u,v);S.insert(i);}
	DFZ(getrt(1,n),1);
	m=gi();
	for(i=1;i<=m;i++){
		scanf("%s",op);
		if(op[0]=='G'){
			if(con==0)printf("-1\n");
			else if(con==1)printf("0\n");
			else{
				u=*(S.begin());
				v=getfarest(u).pos;
				printf("%d\n",getfarest(v).mx);
			}
		}
		else{
			u=gi();
			if(sta[u]){
				con++;sta[u]=0;S.insert(u);
				for(t=dfa[u];t;t=dfa[t])
					insert(T[t],dfn[dep[t]][u],dis[dep[t]][u]);
			}
			else{
				con--;sta[u]=1;S.erase(u);
				for(t=dfa[u];t;t=dfa[t])
					insert(T[t],dfn[dep[t]][u],-dis[dep[t]][u]);
			}
		}
	}
}