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

    题目描述

    从出发点开始依次修改路径上的点权值,然后就是+1或-1的问题。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int N=3e5+7;
    struct node{
        int v,nxt;
    }e[N<<1];
    int n,Enum,tim;
    int front[N],a[N],tree[N<<2],lazy[N<<2];
    int fat[N],son[N],siz[N],tid[N],top[N],dep[N];
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    void Insert(int u,int v)
    {
        e[++Enum].v=v;
        e[Enum].nxt=front[u];
        front[u]=Enum;
    }
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=front[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(v==fat[x])continue;
            fat[v]=x;
            dep[v]=dep[x]+1;
            dfs1(v);
            siz[x]+=siz[v];
            if(siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        tid[x]=++tim;
        if(!son[x])return;
        dfs2(son[x],tp);
        for(int i=front[x];i;i=e[i].nxt)
            if(e[i].v!=son[x] && e[i].v!=fat[x])
                dfs2(e[i].v,e[i].v);
    }
    void PushDown(int rt)
    {
        if(lazy[rt])
        {
            tree[rt<<1]+=lazy[rt];
            tree[rt<<1|1]+=lazy[rt];
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            lazy[rt]=0;
        }
    }
    void Modify(int l,int r,int rt,int nowl,int nowr,int v)
    {
        if(nowl<=l && r<=nowr)
        {
            tree[rt]+=v;
            lazy[rt]+=v;
            return;
        }
        PushDown(rt);
        int mid=l+r>>1;
        if(nowl<=mid)Modify(l,mid,rt<<1,nowl,nowr,v);
        if(mid<nowr)Modify(mid+1,r,rt<<1|1,nowl,nowr,v);
    }
    int Query(int l,int r,int rt,int p)
    {
        if(l==r)return tree[rt];
        PushDown(rt);
        int mid=l+r>>1;
        if(p<=mid)return Query(l,mid,rt<<1,p);
        else return Query(mid+1,r,rt<<1|1,p);
    }
    void ModifyRoad(int x,int y)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
            Modify(1,n,1,tid[f1],tid[x],1);
            x=fat[f1];f1=top[x];
        }
        if(dep[x]>dep[y])swap(x,y);
        Modify(1,n,1,tid[x],tid[y],1);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            a[i]=qread();
        int u,v;
        for(int i=1;i<n;i++)
        {
            u=qread();v=qread();
            Insert(u,v);
            Insert(v,u);
        }
        dfs1(1);dfs2(1,1);
        int now=a[1];
        for(int i=2;i<=n;i++)
        {
            ModifyRoad(now,a[i]);
            now=a[i];
            Modify(1,n,1,tid[now],tid[now],-1);
        }
        for(int i=1;i<=n;i++)
            printf("%d
    ",Query(1,n,1,tid[i]));
        return 0;
    }

    另附一种树上差分的做法

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int N=3e5+7;
    struct node{
        int v,nxt;
    }e[N<<1];
    int n,Enum;
    int front[N],cnt[N],a[N];
    int fat[N],son[N],top[N],siz[N],dep[N];
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    void Insert(int u,int v)
    {
        e[++Enum].v=v;
        e[Enum].nxt=front[u];
        front[u]=Enum;
    }
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=front[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(v==fat[x])continue;
            fat[v]=x;
            dep[v]=dep[x]+1;
            dfs1(v);
            siz[x]+=siz[v];
            if(siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        if(!son[x])return;
        dfs2(son[x],tp);
        for(int i=front[x];i;i=e[i].nxt)
            if(e[i].v!=son[x] && e[i].v!=fat[x])
                dfs2(e[i].v,e[i].v);
    }
    int Lca(int x,int y)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
            x=fat[f1];f1=top[x];
        }
        if(dep[x]<dep[y])return x;
        return y;
    }
    void dfs3(int x)
    {
        for(int i=front[x];i;i=e[i].nxt)
            if(e[i].v!=fat[x])
            {
                dfs3(e[i].v);
                cnt[x]+=cnt[e[i].v];
            }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            a[i]=qread();
        int u,v;
        for(int i=1;i<n;i++)
        {
            u=qread();v=qread();
            Insert(u,v);
            Insert(v,u);
        }
        dfs1(1);dfs2(1,1);
        int lca;
        for(int i=1;i<n;i++)
        {
            lca=Lca(a[i],a[i+1]);
            cnt[a[i]]++;cnt[a[i+1]]++;
            cnt[lca]--;cnt[fat[lca]]--;
        }
        dfs3(1);
        for(int i=2;i<=n;i++)
            cnt[a[i]]--;
        for(int i=1;i<=n;i++)
            printf("%d
    ",cnt[i]);
        return 0;
    }
    树上差分
  • 相关阅读:
    vue-router 滚动行为封装示例
    HTML5 History 模式 后端ngnix配置
    vue-router 嵌套命名视图
    npm 源管理 nrm
    windows系统git使用zip命令报错解决方法
    vue v-html 动态内容样式无效解决方法
    vue 项目打包 本地预览
    Vue 项目环境变量
    Oracle中的统计信息
    宽表和窄表的区别---字段
  • 原文地址:https://www.cnblogs.com/LeTri/p/8718321.html
Copyright © 2011-2022 走看看