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

    题目描述

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有(n-1)根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

    松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去(a_1),再去(a_2),......,最后到(a_n),去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

    维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。

    因为松鼠参观指南上的最后一个房间(a_n)是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

    输入输出格式

    输入格式:

    第一行一个整数(n),表示房间个数第二行(n)个整数,依次描述(a_1-a_n)

    接下来(n-1)行,每行两个整数(x)(y),表示标号(x)(y)的两个房间之间有树枝相连。

    输出格式:

    一共(n)行,第(i)行输出标号为(i)的房间至少需要放多少个糖果,才能让维尼有糖果吃。

    输入输出样例

    输入样例#1:

    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5
    

    输出样例#1:

    1
    2
    1
    2
    1
    

    说明

    (2 leq n leq 300000)

    思路:考虑树链剖分+线段树,我们自己手玩样例可以发现,我们按题目中给出的结点访问顺序进行路径修改,最后把每条路径的起点的点权(-1)(除了起始结点),就是答案了,然后就是一个树链剖分的裸题了。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #define maxn 300007
    #define ls rt<<1
    #define rs rt<<1|1
    using namespace std;
    int n,m,head[maxn],d[maxn],son[maxn],siz[maxn],id[maxn],w[maxn];
    int num,cnt,sum[maxn<<2],top[maxn],fa[maxn],lazy[maxn<<2];
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    struct node {
      int v,nxt;
    }e[maxn<<1];
    inline void ct(int u, int v) {
      e[++num].v=v;
      e[num].nxt=head[u];
      head[u]=num;
    }
    inline void pushdown(int rt) {
      if(lazy[rt]) {
        sum[ls]+=lazy[rt],sum[rs]+=lazy[rt];
        lazy[ls]+=lazy[rt],lazy[rs]+=lazy[rt];
        lazy[rt]=0;
      }
    }
    void modify(int rt, int l, int r, int L, int R, int val) {
      if(L>r||R<l) return;
      if(L<=l&&r<=R) {
        sum[rt]+=val;
        lazy[rt]+=val;
        return;
      }
      pushdown(rt);
      int mid=(l+r)>>1;
      modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
    }
    int query(int rt, int l, int r, int L) {
      if(l==r) return sum[rt];
      int mid=(l+r)>>1;
      pushdown(rt);
      if(L<=mid) return query(ls,l,mid,L);
      else return query(rs,mid+1,r,L);
    }
    void dfs1(int u) {
      siz[u]=1;
      for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v!=fa[u]) {
          d[v]=d[u]+1;
          fa[v]=u;
          dfs1(v);
          siz[u]+=siz[v];
          if(siz[v]>siz[son[u]]) son[u]=v;
        }
      }
    }
    void dfs2(int u, int t) {
      id[u]=++cnt;
      top[u]=t;
      if(son[u]) dfs2(son[u],t);
      for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
      }
    }
    void cal(int x, int y) {
      int fx=top[x],fy=top[y];
      while(fx!=fy) {
        if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
        modify(1,1,cnt,id[fx],id[x],1);
        x=fa[fx],fx=top[x];
      }
      if(id[x]>id[y]) swap(x,y);
      modify(1,1,cnt,id[x],id[y],1);
    }
    int main() {
      n=qread();
      for(int i=1;i<=n;++i) w[i]=qread();
      for(int i=1,u,v;i<n;++i) {
        u=qread(),v=qread();
        ct(u,v);ct(v,u);
      }
      dfs1(1),dfs2(1,1);
      int now=w[1];
      for(int i=2;i<=n;++i) {
        cal(now,w[i]);
        now=w[i];
        modify(1,1,cnt,id[now],id[now],-1);
      }
      for(int i=1;i<=n;++i) printf("%d
    ",query(1,1,cnt,id[i]));
      return 0;
    }
    
  • 相关阅读:
    跨平台编译ceres for Android
    解决OpenCV JavaCameraView相机preview方向问题
    OpenCV 4.0.1 找不到R.styleable解决
    mumu模拟器安装xposed--如何在android模拟器上进行root
    Windows编译OpenCV4Android解决undefined reference to std错误
    Skeleton with Assimp 骨骼动画解析
    Android GL deadlock timeout error
    Android device debug (adb) by Charge Only mode
    Firefox 多行标签的解决方案分享
    Linux 工程向 Windows 平台迁移的一些小小 tips
  • 原文地址:https://www.cnblogs.com/grcyh/p/10201655.html
Copyright © 2011-2022 走看看