BZOJ1095

动态点分治,先搞出重心树,对于重心树的每一个节点维护两个队q1,q2,前者维护当前子树到父重心(重心树中的父亲???)的距离,后者维护当前节点每一个出度的q1堆顶,再全局维护一个ans,即所有节点q2的最大值和次大值……
被坑点:
1、一开始求出第一个重心后,dfs要从重心开始搜!!!
2、 dep[x]+dep[y]-2*dep[lca(x,y)];注意要 2 !!!
3、开anc数组要开大一点!!!不然就会越界!!!本来开了17,后来发现循环时从17开始扫……
4、乱压行会死得很惨!!!注意优先级!!!

//http://www.cnblogs.com/juruolty/p/6502677.html
#include 
#include 
#include 
#include 
#define maxn 100000+10
#define read(x) scanf("%d",&x)

using namespace std;
int i,j,dep[maxn],rot,c,now_sz,f[maxn],a[maxn],x,T,y,off_tot,n,m,head[maxn];
int anc[maxn][20],g[maxn]={9999999999},sz[maxn],vis[maxn];
char s[10];
struct xx{
    int v,next;
}b[maxn<<1];

struct heap{
    priority_queue<int> ad,del;
    void _push(int x){ad.push(x);};
    void _pop(int x){del.push(x);};
    int _top(){while (del.size()&&ad.top()==del.top()) ad.pop(),del.pop();return ad.top();}
    int get_two(){int a,b;return a=_top(),ad.pop(),b=_top(),_push(a),a+b;}
    int sz(){return ad.size()-del.size();}
}ans,q1[maxn],q2[maxn];//q1表示子树节点到父重心距离,
                       //q2表示子节点q1堆顶,
                       //ans表示所有重心q2堆顶 

void add(int u,int v)
{
    b[++m]=(xx){v,head[u]};
    head[u]=m;
}

int lca(int p,int q)
{
    if (dep[p]for (int i=17;i>=0;--i)
      if (dep[p]-(1<=dep[q]) p=anc[p][i];
    if (p==q) return p;
    for (int i=17;i>=0;--i) 
      if (anc[p][i]^anc[q][i]) p=anc[p][i],q=anc[q][i];
    return anc[p][0];
}

int ds(int x,int y)
{
    return dep[x]+dep[y]-2*dep[lca(x,y)];
}

int cal(int x)//turn_off x
{
    int u=x;
    if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
    q2[x]._push(0);
    if (q2[x].sz()>=2) ans._push(q2[x].get_two());
    while (f[u])
    {

        if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
        if (q1[u].sz()) q2[f[u]]._pop(q1[u]._top());
        q1[u]._push(ds(f[u],x));
        q2[f[u]]._push(q1[u]._top());
        if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
        u=f[u];
    }
}

int cal2(int x)//turn_on x
{
    int u=x;
    if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
    q2[x]._pop(0);
    if (q2[x].sz()>=2) ans._push(q2[x].get_two());
    while (f[u])
    {
        if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
        q2[f[u]]._pop(q1[u]._top());
        q1[u]._pop(ds(f[u],x));
        if (q1[u].sz()) q2[f[u]]._push(q1[u]._top());
        if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
        u=f[u];
    }
}

void get_rot(int x,int fa)
{
    sz[x]=1;g[x]=0;
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (v==fa||vis[v]) continue;
        get_rot(v,x);
        sz[x]+=sz[v];
        g[x]=max(g[x],sz[v]);
    }
    g[x]=max(g[x],now_sz-sz[x]);
    rot=g[x]void build(int x)
{
    vis[x]=1;
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (vis[v]) continue;
        rot=0;now_sz=sz[v];
        get_rot(v,0);
        f[rot]=x;
        build(rot);
    }
}

void dfs(int x,int fa)
{
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (v==fa) continue;
        dep[v]=dep[x]+1;
        anc[v][0]=x;
        dfs(v,x);
    }
}

int main()
{

    read(n);
    for ( i=1;i0,get_rot(1,0),dep[rot]=1,dfs(rot,0),build(rot);
    for ( j=1;j<17;++j)
     for ( i=1;i<=n;++i) 
      anc[i][j]=anc[anc[i][j-1]][j-1];
    for ( i=1;i<=n;++i) cal(i);
    read(T);
    off_tot=n;
    while (T--)
        scanf("%s",s),s[0]=='G'?printf("%d\n",off_tot<=1?off_tot-1:ans._top()):
        (((read(x)),a[x]=a[x]==1?0:1)?(--off_tot,cal2(x)):(++off_tot,cal(x)));
    return 0;
} 

你可能感兴趣的:(OI)