Luogu2056 [ZJOI2007]捉迷藏

Luogu2056 [ZJOI2007]捉迷藏

这道题是最远点对问题,考虑如何用点分治维护最远点对。

那么对于每一个点,我们只需要找到最长链次长链(如果有的话),由于需要动态维护点分树,我们需要数据结构,可删除堆可以胜任这一任务(以下提到的均为可删除堆,关于可删除堆的操作细节,这里就不谈了,现在我才知道自己写的可删除堆是如此逊,不会用两个堆写到爆炸)。

但是不能忘记,如果我们要计算一个节点\(u\)控制的连通块\(T_u\)答案,在这两条链是不能同时存在于\(u\)的同一颗子树内的。

那么对于每一棵子树\(v\)维护一个堆\(H_{u,v}\),再用每一棵子树的堆顶元素丢进一个堆\(R_{u}\)里,那么\(R_{u}\)的前两大元素即为连通块\(T_u\)内的最长链。

由于我们需要求全局答案,因此我们还需要维护一个堆\(ans\),容纳所有\(R_x\)的堆顶元素最大值。

于是变成了堆套堆套堆,十分奇怪。

然后我们考虑修改,从询问节点\(x\)开始往上跳到点分树根,由于我们维护的是堆套堆套堆,所以我们每次修改都需要修改\(3\)个堆,先修改底层的\(H\),再修改\(R\),最后修改\(ans\)

然后,就被卡常了。。。

关于卡常的坎坷,这里不再叙述(常数大怪谁呢,口胡可删除堆怪谁呢)。

注:以下代码中没有把\(dis_{u,u}=0\)丢进\(R_u\)中,因此如果\(R_u\)中只有一条链,那么需要特判\(u\)是否被点亮,如果没被点亮,这条链答案是需要统计进去的,否则不能统计(只有一个端点)。

\(Code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<tr1/unordered_map>
#define N 100005
#define INF 1000000007
#define rint register int
#define il inline
#define pr pair<int,int>
#define mp make_pair
#define IT vector<int> :: iterator
using namespace std;
using namespace std :: tr1;
int n,m,x,y,o;
int tot,fr[N],nxt[N << 1],d[N << 1];
int lsz,rtsz,rt,ct,f[N],sz[N];
int crt,trt,krt,light;
char opt;
bool vis[N],op[N];
int tr[N];
int tc,bg[N],lg2[N << 1],dep[N],dfn[N << 1],st[N << 1][20];
char buf[1 << 23],*p1=buf,*p2=buf,obuf[1 << 23],*O=obuf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1 << 21,stdin),p1==p2)?EOF:*p1++)
unordered_map<int,int>r[N];
unordered_map<int,int>g[N << 1];
struct Heap
{
    vector<int>a;
    vector<int>c;
    int cnt,id;
    il pr top()
    {
        return mp(a[1],c[1]);
    }
    il bool empty()
    {
        return cnt==0;
    }
    il int size()
    {
        return cnt;
    }
    il void push(int x,int z)
    {
        ++cnt;
        a.push_back(x);
        c.push_back(z);
        g[id][z]=cnt;
        int t=cnt;
        while (t>1 && a[t]>a[t >> 1])
        {
            swap(g[id][c[t]],g[id][c[t >> 1]]);
            swap(a[t],a[t >> 1]);
            swap(c[t],c[t >> 1]);
            t >>=1;
        }
    }
    il void pop()
    {
        swap(g[id][c[cnt]],g[id][c[1]]);
        swap(a[cnt],a[1]);
        swap(c[cnt],c[1]);
        g[id][c[cnt]]=0;
        a.erase(a.end()-1);
        c.erase(c.end()-1);
        cnt--;
        int t=1;
        while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
            if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
                swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
                swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
    }
    il void pop_point(int z)
    {
        int wz=g[id][z];
        if (!wz)
            return;
        swap(g[id][c[cnt]],g[id][c[wz]]);
        swap(a[cnt],a[wz]);
        swap(c[cnt],c[wz]);
        g[id][c[cnt]]=0;
        a.erase(a.end()-1);
        c.erase(c.end()-1);
        cnt--;
        int t=wz;
        while (t>1 && a[t]>a[t >> 1])
        {
            swap(g[id][c[t]],g[id][c[t >> 1]]);
            swap(a[t],a[t >> 1]);
            swap(c[t],c[t >> 1]);
            t >>=1;
        }
        while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
            if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
                swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
                swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
    }
    void update_point(int x,int z)
    {
        int wz=g[id][z];
        if (!wz)
        {
            push(x,z);
            return;
        }
        a[wz]=x;
        int t=wz;
        while (t>1 && a[t]>a[t >> 1])
        {
            swap(g[id][c[t]],g[id][c[t >> 1]]);
            swap(a[t],a[t >> 1]);
            swap(c[t],c[t >> 1]);
            t >>=1;
        }
        while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
            if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
                swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
                swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
    }
}e[N << 1];
il int cmx(int x,int y)
{
    return (x>y)?x:y;
}
il void ins(int x,int y)
{
    r[x][y]=++ct;
    e[ct].id=ct;
    e[ct].cnt=0;
    e[ct].a.push_back(0);
    e[ct].c.push_back(0);
}
il void ins(int x)
{
    tr[x]=++ct;
    e[ct].id=ct;
    e[ct].cnt=0;
    e[ct].a.push_back(0);
    e[ct].c.push_back(0);
}
il int ans(int x,int tx)
{
    if (!x)
        return (!light)?(-1):((light^1)?e[x].top().first:0);
    if (e[x].empty())
        return 0;
    return (e[x].size()==1)?(op[tx]?0:e[x].a[1]):((e[x].size()==2)?e[x].a[1]+e[x].a[2]:e[x].a[1]+cmx(e[x].a[2],e[x].a[3]));
}
il int read()
{
    int s=0;
    char c=getchar();
    while (c<'0' || c>'9')
        c=getchar();
    while ('0'<=c && c<='9')
        s=(s << 1)+(s << 3)+(c^48),c=getchar();
    return s;
}
il void write(int x)
{
    if (x<0)
        *O++='-',write(-x); else
        {
            if (x>9)
                write(x/10);
            *O++=x%10+'0';
        }
}
il void add(int x,int y)
{
    tot++;
    d[tot]=y;
    nxt[tot]=fr[x];
    fr[x]=tot;
}
il void dfs(int u,int F)
{
    dfn[++tc]=u;
    bg[u]=tc;
    for (rint i=fr[u];i;i=nxt[i])
    {
        int v=d[i];
        if (v==F)
            continue;
        dep[v]=dep[u]+1;
        dfs(v,u);
        dfn[++tc]=u;
    }
}
il int lca(int x,int y)
{
    x=bg[x],y=bg[y];
    if (x>y)
        swap(x,y);
    int k=lg2[y-x+1];
    return (dep[st[x][k]]<dep[st[y-(1 << k)+1][k]])?st[x][k]:st[y-(1 << k)+1][k];
}
il int ds(int x,int y)
{
    return dep[x]+dep[y]-(dep[lca(x,y)] << 1);
}
il void findrt(int u,int F,int rn)
{
    int mx=-1;
    sz[u]=1;
    for (rint i=fr[u];i;i=nxt[i])
    {
        int v=d[i];
        if (v==F || vis[v])
            continue;
        findrt(v,u,rn);
        sz[u]+=sz[v];
        if (sz[v]>mx)
            mx=sz[v];
    }
    mx=cmx(mx,rn-sz[u]);
    if (mx<rtsz)
        rtsz=mx,rt=u;
}
il void getrt(int u,int rn)
{
    rtsz=INF;
    findrt(u,0,rn);
}
il void update_dis(int u,int F)
{
    e[crt].push(ds(trt,u),u);
    for (rint i=fr[u];i;i=nxt[i])
    {
        int v=d[i];
        if (v==F || vis[v])
            continue;
        update_dis(v,u);
    }
}
il void solve(int u)
{
    int tsz=lsz;
    vis[u]=true;
    if (tsz==1)
        return;
    ins(u);
    for (rint i=fr[u];i;i=nxt[i])
    {
        int v=d[i];
        if (vis[v])
            continue;
        lsz=(sz[v]<sz[u])?sz[v]:tsz-sz[u];
        getrt(v,lsz);
        f[rt]=u;
        ins(u,rt);
        trt=u,krt=rt,crt=ct;
        update_dis(v,u);
        e[tr[u]].push(e[ct].top().first,rt);
        solve(rt);
    }
    e[0].push(ans(tr[u],u),u);
}
il void insr(int x,int t,int y)
{
    o=r[x][t];
    e[o].push(ds(x,y),y);
    e[tr[x]].update_point(e[o].top().first,t);
    e[0].update_point(ans(tr[x],x),x);
}
il void del(int x,int t,int y)
{
    o=r[x][t];
    e[o].pop_point(y);
    if (e[o].empty())
        e[tr[x]].pop_point(t); else
        e[tr[x]].update_point(e[o].top().first,t);
    if (e[tr[x]].empty())
        e[0].pop_point(x); else
        e[0].update_point(ans(tr[x],x),x);
}
il void update(int x,int opt)
{
    int u=x;
    while (f[u])
    {
        if (!opt)
            insr(f[u],u,x); else
            del(f[u],u,x);
        u=f[u];
    }
}
int main()
{
    n=read();
    for (rint i=1;i<n;++i)
    {
        x=read(),y=read();
        add(x,y),add(y,x);
    }
    dep[1]=1;
    dfs(1,0);
    lg2[0]=-1;
    for (rint i=1;i<=tc;++i)
        st[i][0]=dfn[i],lg2[i]=lg2[i >> 1]+1;
    for (rint j=1;j<=lg2[tc];++j)
        for (rint i=1;i<=tc-(1 << j)+1;++i)
            st[i][j]=(dep[st[i][j-1]]<dep[st[i+(1 << (j-1))][j-1]])?st[i][j-1]:st[i+(1 << (j-1))][j-1];
    ct=0;
    e[ct].id=ct;
    e[ct].cnt=0;
    e[ct].a.push_back(0);
    e[ct].c.push_back(0);
    lsz=n;
    getrt(1,lsz);
    solve(rt);
    light=n;
    m=read();
    for (rint i=1;i<=m;++i)
    {
        opt=getchar();
        while (opt!='C' && opt!='G')
            opt=getchar();
        if (opt=='G')
            write(ans(0,0)),*O++='\n'; else
            {
                x=read();
                int tt=-1;
                if (op[x])
                    light++,op[x]=false,tt=0; else
                    light--,op[x]=true,tt=1;
                update(x,tt);
            }
    }
    fwrite(obuf,O-obuf,1,stdout);
    return 0;
}
posted @ 2020-10-19 16:39  GK0328  阅读(72)  评论(0编辑  收藏  举报