• BZOJ 3631 JLO2014 I松鼠的新家


    3631: [JLOI2014]松鼠的新家

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2396  Solved: 1244
    [Submit][Status][Discuss]

    Description

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
    可是这样会导致**重复走很多房间,懒惰的**不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。**是个馋家伙,立马就答应了。
    现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

    Input

    第一行一个整数n,表示房间个数
    第二行n个整数,依次描述a1-an
    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

    Output

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

    Sample Input

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

    Sample Output

    1
    2
    1
    2
    1

    HINT 

    2<= n <=300000

    利用树上差分,从x走到y可以看作x走到lca(x,y),再从lca(x,y)走到y
    我们让x和y点的权值加1,lca(x,y)的权值-1,lca(x,y)的父节点的权值也减一
    最后自下向上递归求出每一个点的权值,累加即可
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long;
    char buf[1<<15],*fs,*ft;
    inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    inline int read(){
    int x=0,f=1;  char ch=getc();
    while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
    while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
    return x*f;
    }
    void put(int x){
    if(x==0){
    putchar('0');
    putchar('
    ');
    return;
    }
    if(x<0){
    putchar('-');
    x=-x;
    }
    int num=0;char ch[16];
    while(x) ch[++num]=x%10+'0',x/=10;
    while(num) putchar(ch[num--]);
    putchar('
    ');
    }
    const int MAXN=500010;
    namespace zhangenming{
     struct node{
      int y,next;
     }e[MAXN<<1];
     int linkk[MAXN<<1],fa[MAXN][30]={},len=0,n,a[MAXN],dep[MAXN],value[MAXN];
     inline void insert(int xx,int yy){
      e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;
     }
     void init(){
      n=read();
      for(int i=1;i<=n;i++){
       a[i]=read();
      }
      for(int i=1;i<n;i++){
       int xx=read();int yy=read();
       insert(xx,yy);
       insert(yy,xx);
      }
     }
     void dfs(int father,int st,int depth){
      fa[st][0]=father;dep[st]=depth;
      for(int i=linkk[st];i;i=e[i].next){
       if(e[i].y!=father){
        dfs(st,e[i].y,depth+1);
       }
      }
     }
     void getanser(){
      for(int i=1;i<=20;i++){
       for(int j=1;j<=n;j++){
        if(fa[j][i-1]!=0) fa[j][i]=fa[fa[j][i-1]][i-1];
        //cout<<fa[j][i]<<' ';
       }
      }
     }
     void dfs2(int st,int father){
      for(int i=linkk[st];i;i=e[i].next){
       if(e[i].y!=father){
        dfs2(e[i].y,st);
        value[st]+=value[e[i].y];
       }
      }
     }
     int LCA(int xx,int yy){
      if(xx==yy) return xx;
      if(dep[xx]<dep[yy]) swap(xx,yy);
      for(int i=20;i>=0;i--){
       if(dep[xx]-(1<<i)>=dep[yy]){
        xx=fa[xx][i];
       } 
      }
      if(xx==yy) return xx;
      for(int i=20;i>=0;i--){
       if(fa[xx][i]!=fa[yy][i]&&fa[xx][i]!=0){
        xx=fa[xx][i];yy=fa[yy][i];
       }
      }
      return fa[xx][0];
     }
     void print(){
      for(int i=1;i<=n;i++){
       put(value[i]);
      }
     }
     void solve(){
      dfs(0,1,0);
      getanser();
      for(int i=1;i<n;i++){
       int xx=a[i];int yy=a[i+1];
       int lca=LCA(xx,yy);
       value[xx]++;value[yy]++;value[lca]--;value[fa[lca][0]]--;
      }
      dfs2(1,0);
      for(int i=2;i<=n;i++){
       value[a[i]]--;
      }
     }
    }
    int main(){
     using namespace zhangenming;
     init();
     solve();
     print();
     return 0;
    }
    

      

  • 相关阅读:
    0114 Handler(一)
    0110Activity布局初步2+0111布局初步3
    0108 Activity的生命周期(二)+显示文本的几种方法+调用发送短信(Intent)
    消除超级连接虚线
    ASP.NET数据绑定(转载)
    ASP.NET实现数字签名(转载)
    datatable插入数据库(转载)
    JavaScript(转载)
    Jquery插件按开发学习笔记(一)
    js判断浏览器\屏幕分辨率(转载)
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7861568.html
Copyright © 2020-2023  润新知