首先要知道点分治和点分树(大家应该都懂的)
点分树的高度是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]);
}
}
}
}