zoukankan      html  css  js  c++  java
  • 【BZOJ3631】【JLOI2014】松鼠的新家

    原题传送门

    题意:给你一棵树,然后有一个遍历顺序,你需要补全这个遍历顺序,然后输出这个遍历顺序中每个点的出现次数。

    解题思路:本来想找树剖的题,结果发现了一题可以直接写lca的。。。。

    做法1:非常简单的NOIP式做法就是tjlca后直接树上差分即可。时间效率( O(n) )(常数较大).(BZOJ上1064ms)

    #include <stdio.h>
    #include <string.h>
    #define MN 300005
    #define v edge[i].to
    struct link{int to,nxt;}edge[MN<<4];
    int cf[MN],h[MN],q[MN],a[MN],n,cnt,lca[MN],fa[MN],f[MN];
    inline int in(){
        int x=0;bool f=0; char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-',ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return f?-x:x;
    }
    inline void ins(int *h,int x,int y){edge[++cnt].to=y,edge[cnt].nxt=h[x],h[x]=cnt;}
    inline void insw(int x,int y){ins(h,x,y);ins(h,y,x);}
    inline int getfa(int x){return fa[x]?fa[x]=getfa(fa[x]):x;}
    inline void tjlca(int u){
        for (register int i=h[u]; i; i=edge[i].nxt)
            if (v!=f[u]) f[v]=u,tjlca(v),fa[v]=u;
        for (register int i=q[u]; i; i=edge[i].nxt)
            if (lca[v]) lca[v]=getfa(lca[v]);
            else lca[v]=u;
    }
    inline void dfs(int u){
        for (register int i=h[u]; i; i=edge[i].nxt)
            if (v!=f[u]) dfs(v),cf[u]+=cf[v];
    }
    void init(){
        n=in();for (int i=1; i<=n; ++i) a[i]=in(),ins(q,a[i],i),ins(q,a[i],i-1);
        for (register int i=1; i<n; ++i) insw(in(),in());
    }
    void solve(){
        tjlca(1);for (register int i=1; i<n; ++i)
            ++cf[a[i]],++cf[a[i+1]],--cf[lca[i]],--cf[f[lca[i]]];dfs(1);
        for (register int i=2; i<=n; ++i) --cf[a[i]];
        for (register int i=1; i<=n; ++i) printf("%d
    ",cf[i]);
    }
    int main(){init(); solve(); return 0;}

    做法2:用树剖代替lca,用差分序列维护剖下来的树,也可以直接AC。时间效率为( O(n log log n)) ~(O(n log n) )。(BZOJ 792ms)

    #include <stdio.h>
    #define MN 300005
    int cnt,to[MN<<1],nxt[MN<<1];
    int head[MN],siz[MN],son[MN],dep[MN],a[MN],top[MN],fa[MN],pos[MN],n,d[MN],dfsn;
    inline int in(){
        int x=0;bool f=0; char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-',ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return f?-x:x;
    }
    inline void ins(int x,int y){to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;}
    inline void insw(int x,int y){ins(x,y);ins(y,x);};
    inline void swp(int &a,int &b){a^=b^=a^=b;}
    inline void dfs1(int u,int f,int d){
        siz[u]=1,fa[u]=f,dep[u]=d;
        for (register int i=head[u]; i; i=nxt[i])
            if (to[i]!=f){
                dfs1(to[i],u,d+1);siz[u]+=siz[to[i]];
                if (siz[to[i]]>siz[son[u]]) son[u]=to[i];
            }
    }
    inline void dfs2(int u,int tp){
        top[u]=tp,pos[u]=(++dfsn);if (son[u]) dfs2(son[u],tp);
        for (register int i=head[u]; i; i=nxt[i])
            if (to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i]);
    }
    inline void update(int x,int y){
        while(top[x]!=top[y]){
            if (dep[top[x]]<dep[top[y]]) swp(x,y);
            ++d[pos[top[x]]],--d[pos[x]+1];x=fa[top[x]];
        }if (dep[x]>dep[y]) swp(x,y);++d[pos[x]],--d[pos[y]+1];
    }
    void init(){
        n=in();for (register int i=1; i<=n; ++i) a[i]=in();
        for (register int i=1; i<n; ++i) insw(in(),in());
        dfs1(1,1,1);dfs2(1,1);
    }
    void solve(){
        for (register int i=1; i<n; ++i) {
            update(a[i],a[i+1]);    
            if (i!=1) --d[pos[a[i]]],++d[pos[a[i]]+1];
        }--d[pos[a[n]]],++d[pos[a[n]]+1];
        for (register int i=1; i<=n; ++i) d[i]+=d[i-1];
        for (register int i=1; i<=n; ++i)
            printf("%d
    ",d[pos[i]]);
    }
    int main(){init(); solve(); return 0;}
  • 相关阅读:
    20121010 闲的慌的日子
    九月,桂花飘香的季节
    win7下控件(ActiveX)注册错误(0x80040200) 修正
    C#多线程技术(一)
    C#多线程技术(二)
    C++沉思录摘录(OOP部分)
    SVM入门教程
    是IE的bug还是Windows的bug?
    inno setup安装时不需要开始菜单项
    django本地局域网访问
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ3631.html
Copyright © 2011-2022 走看看