zoukankan      html  css  js  c++  java
  • [BZOJ3631][JLOI2014]松鼠的新家

    嗯。。。企图做ZJOI2011,结果一题都不会QAQ。生气的写树剖来了~

    这题暴力的树剖是可以的,但我是在黄学长那找了这题,他好像有个非常妙的做法,现在差不多要去打ball了,之后再学习一下吧。

    树剖:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    typedef long long LL;
    using namespace std;
    const int N=300010;
    struct edge{int to,nxt;}e[N<<1];
    struct node{int l,r,lazy;}a[N<<2];
    int n,b[N],head[N],cnt,pos[N],siz[N],bel[N],fa[N];
    int read() {int d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;}
    void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);}
    void addedge(int x,int y)
    {
        e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
        e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
    }
    void dfs(int u)
    {
        siz[u]=1;
        for (int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if (v==fa[u]) continue;
            fa[v]=u; dfs(v); siz[u]+=siz[v];
        }
    }
    void dfs2(int u,int Bel)
    {
        pos[u]=++cnt; bel[u]=Bel;
        int x=0;
        for (int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if (v==fa[u]) continue;
            if (siz[v]>siz[x]) x=v;
        }
        if (!x) return;
        dfs2(x,Bel);
        for (int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if (v==fa[u]||v==x) continue;
            dfs2(v,v);
        }
    }
    void pushdown(int k)
    {
        if (!a[k].lazy) return;
        int k1=k<<1,k2=k1|1;
        a[k1].lazy+=a[k].lazy; a[k2].lazy+=a[k].lazy;
        a[k].lazy=0;
    }
    void build(int k,int l,int r)
    {
        a[k]=(node){l,r,0};
        if (l==r) return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid); build(k<<1|1,mid+1,r);
    }
    void update(int k,int l,int r,int v)
    {
        if (l<=a[k].l&&a[k].r<=r) {a[k].lazy+=v; return;}
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
        if (r<=mid) update(k<<1,l,r,v);
        else if (l>mid) update(k<<1|1,l,r,v);
        else update(k<<1,l,mid,v),update(k<<1|1,mid+1,r,v);
    }
    int ask(int k,int x)
    {
        if (a[k].l==a[k].r) return a[k].lazy;
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
        if (x<=mid) return ask(k<<1,x);
        else return ask(k<<1|1,x);
    }
    int main()
    {
        //judge();
        n=read();
        for (int i=1;i<=n;i++) b[i]=read();
        for (int i=1;i<n;i++) addedge(read(),read());
        dfs(1); cnt=0; dfs2(1,1); build(1,1,n);
        int x=b[1];
        for (int i=2;i<=n;i++)
        {
            int y=b[i];
            while (bel[x]!=bel[y])
            {
                if (pos[x]<pos[y]) swap(x,y);
                update(1,pos[bel[x]],pos[x],1);
                x=fa[bel[x]];
            }
            if (pos[x]>pos[y]) swap(x,y);
            update(1,pos[x],pos[y],1);
            x=b[i];
            update(1,pos[x],pos[x],-1);
        }
        for (int i=1;i<=n;i++) printf("%d
    ",ask(1,pos[i]));
        return 0;
    }
    View Code

    未完待续...

    摘自黄学长:http://hzwer.com/4522.html

    其实是可以直接上树链剖分的

    但是我们发现这道题只要实现每次将u-v路径的点权+1

    只要在u和v上打个+1标记,lca(u,v)和lca(u,v)->fa打-1标记,最后dp上传标记即可

    本质是个差分。。。

    代码就不写了~(≧▽≦)/~啦啦啦

    完结~

  • 相关阅读:
    ACM士兵排队
    ACM两个士兵打牌
    ACM平衡的括号
    ACM复合词
    ACM第二次比赛( C )
    ACM比赛(第二次A)
    ACM比赛(进制转换)
    ACM比赛(11462 Age Sort)
    ACM比赛
    hdu 1241 Oil Deposits(DFS求连通块)
  • 原文地址:https://www.cnblogs.com/lujiaju6555/p/6789549.html
Copyright © 2011-2022 走看看