• BZOJ1095(动态点分治+堆)


    终于把这个坑填了..

    按重心分治建树,每个点存两个堆,第一个存的是这个点子树中的点到父重心的距离,第二个存的是子节点第一个堆的堆顶,同时有一个全局答案堆,存的是每个点第二个堆的最大值+次大值。

    20亿个蒟蒻们给了我一份漏洞百出的代码,害的我想了半天..

    #include <cstdio>
    #include <queue>
    using namespace std;
    
    const int N=100005,M=200005;
    char op[5];
    int n,e,x,y,q,tt,sm,mn,rt,hd[N],nx[M],to[M],v[N],f[N],a[N],d[N],sz[N],g[N][17];
    struct hep {
        priority_queue<int> ad,dl;
        void pu(int x) {ad.push(x);}
        void po(int x) {dl.push(x);}
        int tp() {while(!dl.empty()&&ad.top()==dl.top()) ad.pop(),dl.pop(); return ad.top();}
        int gt() {int a=tp(); ad.pop(); int b=tp(); ad.push(a); return a+b;}
    }a1,q1[N],q2[N];
    void ad(int x,int y) {to[++e]=y,nx[e]=hd[x],hd[x]=e;}
    
    void dfs2(int x) {for(int i=hd[x];i;i=nx[i]) if(!d[to[i]]) d[to[i]]=d[x]+1,g[to[i]][0]=x,dfs2(to[i]);}
    int lca(int x,int y) {
        if(d[x]<d[y]) swap(x,y);
        for(int i=16;~i;i--) if(d[g[x][i]]>=d[y]) x=g[x][i];
        if(x==y) return x;
        for(int i=16;~i;i--) if(g[x][i]^g[y][i]) x=g[x][i],y=g[y][i];
        return g[x][0];
    }
    int ds(int x,int y) {return d[x]+d[y]-d[lca(x,y)]*2;}
    void dfs(int x,int fa) {
        sz[x]=1;
        for(int i=hd[x];i;i=nx[i]) if(to[i]!=fa&&!v[to[i]]) dfs(to[i],x),sz[x]+=sz[to[i]];
    }
    void gt(int x,int fa) {
        int mx=0; sz[x]=1;
        for(int i=hd[x];i;i=nx[i]) if(to[i]!=fa&&!v[to[i]]) gt(to[i],x),sz[x]+=sz[to[i]],mx=max(mx,sz[to[i]]);
        mx=max(mx,tt-sz[x]);
        if(mx<mn) mn=mx,rt=x;
    }
    void bd(int x,int y) {
        gt(x,0),f[rt]=y,v[rt]=1,dfs(rt,0); int k=rt;
        for(int i=hd[rt];i;i=nx[i]) if(!v[to[i]]) tt=mn=sz[to[i]],bd(to[i],k);
    }
    void cal(int x) {
        int u=x;
        if(q2[x].ad.size()-q2[x].dl.size()>=2) a1.po(q2[x].gt());
        q2[x].pu(0);
        if(q2[x].ad.size()-q2[x].dl.size()>=2) a1.pu(q2[x].gt());
        while(f[u]) {
            if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=2) a1.po(q2[f[u]].gt());
            if(q1[u].ad.size()-q1[u].dl.size()) q2[f[u]].po(q1[u].tp());
            q1[u].pu(ds(f[u],x)),q2[f[u]].pu(q1[u].tp());
            if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=2) a1.pu(q2[f[u]].gt());
            u=f[u];
        }
    }
    void cal2(int x) {
        int u=x;
        if(q2[x].ad.size()-q2[x].dl.size()>=2) a1.po(q2[x].gt());
        q2[x].po(0);
        if(q2[x].ad.size()-q2[x].dl.size()>=2) a1.pu(q2[x].gt());
        while(f[u]) {
            if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=2) a1.po(q2[f[u]].gt());
            q2[f[u]].po(q1[u].tp()),q1[u].po(ds(f[u],x));
            if(q1[u].ad.size()-q1[u].dl.size()) q2[f[u]].pu(q1[u].tp());
            if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=2) a1.pu(q2[f[u]].gt());
            u=f[u];
        }
    }
    
    int main() {
        scanf("%d",&n),sm=n;
        for(int i=1;i<n;i++) scanf("%d%d",&x,&y),ad(x,y),ad(y,x);
        tt=mn=n,bd(1,0),d[1]=1,dfs2(1);
        for(int j=1;j<17;j++)
        for(int i=1;i<=n;i++)
            g[i][j]=g[g[i][j-1]][j-1];
        for(int i=1;i<=n;i++) cal(i);
        scanf("%d",&q);
        while(q--) {
            scanf("%s",op);
            if(op[0]=='G') {
                if(sm<=1) printf("%d
    ",sm-1);
                else printf("%d
    ",a1.tp());
            }
            else {
                scanf("%d",&x),a[x]^=1;
                if(a[x]) sm--,cal2(x); else sm++,cal(x);
            }
        }
        return 0;
    }
  • 相关阅读:
    SQL SERVER 分布式事务(DTC)
    .NET 笔试题--自已作答
    设计模式-观察者模式
    设计模式-迭代器模式
    设计模式-责任链模式
    C#中引用类型和值类型
    另一个 OleDbParameterCollection 中已包含 OleDbParameter 错误分析及解决办法
    R语言笔记-set.seed()函数
    R中的sample函数
    R语言包相关命令
  • 原文地址:https://www.cnblogs.com/juruolty/p/6502677.html
Copyright © 2020-2023  润新知