洛谷—— P3258 [JLOI2014]松鼠的新家

题目描述

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

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

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

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

输入输出格式

输入格式:

第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an接下来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<= n <=300000

思路:

对于这个题有些大佬肯定看一眼就能知道这个题是用的lca+插分做的吧。

(但像我这种蒟蒻是肯定不能一眼就看出来的!)

那有些人就要问啦,插分是个什么鬼?!

好,那我们先来说说插分吧!

随便写一个序列 3 6 2 7 5

它的查分序列是用后一个数减去前一个数,第一个数什么都不减就是它本身。

差分序列 3  3  -4  5  -2

差分序列有一个性质,就是你从头往后累加,加到第几个位置,现在累加的数就是原序列这个位置的数。

例如:差分序列加到第三个位置 3+3+(-4)=2;正好是原序列第三个位置的数。

应用一下吧。。。。我们要对一个区间的子区间进行操作.

例如[1,10];我们要将[4,6]这个区间的所有数加+1,求[4,6]的区间和。当然可以for循环挨个加1,求和;

那么差分是怎样求呢。我们只需更改两个位置,假如我们进行修改的区间是[l,r]。将a[l]+1,a[r+1]-1;即可完成区间的更改。

上面的例子 [4,6] .a[4]+1,a[6+1]-1;这样从头开始累加,由于我们在a[4]+1,我们从头累加到a[4-6]都会加+1;当我们累加到[4,6]

这个区间以外,由于a[6+1]已经-1,所以之后的累加都-1,都是它原来数的大小。为什么累加就是利用的差分序列的性质

来,我们来看看树上差分的结论:

1、将每条路径(s,t)上的每个点权值增加1,求各点权值。

将s、t点的权值加+1,lca(s,t)的权值-1,s和t的lca的爸爸-1。从叶子结点开始向上累加权值。

恍然大悟WAW。这道题真是赤裸裸的一道裸题啊。至于为什么那个点+那个点-,结合差分序列的性质自己顿悟。

2、找出被所有路径都覆盖的边

s,t的权值+1,s和t的lca的权值-2,从叶结点向上累加。

最终权值为路径数的点到其父亲的边为所求边。

所以我们把这个题访问的路径看成一个区间,区间的结点的权值都+1,就用差分做好了。

但是有一个坑,这一条路径的起点是这一条路径的终点,所以不能重复给糖,最后2--n减去1就可以。

好吧,废话少说,我们来直接看这道题的代码吧!

代码:

#include<vector>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 300000+15
using namespace std;
vector<int>vec[N];
int fa[N],deep[N],n,m,top[N],ans,size[N],x,y,f[N],a[N],z;
int read(){
    ,f=;
    char ch=getchar();
    ')
    {
        ;
        ch=getchar();
    }
    ')
    {
        x=x*+ch-';
        ch=getchar();
    }
    return x*f;
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])
          swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])
      swap(x,y);
    return x;
}
void dfs(int x)
{
    size[x]=;
    deep[x]=deep[fa[x]]+;
    ;i<vec[x].size();i++)
      if(vec[x][i]!=fa[x])
      {
          fa[vec[x][i]]=x;
          dfs(vec[x][i]);
          size[x]+=size[vec[x][i]];
      }
}
void dfs1(int x)
{
    ;
    if(!top[x]) top[x]=x;
    ;i<vec[x].size();i++)
      if(vec[x][i]!=fa[x]&&size[vec[x][i]]>size[t])
        t=vec[x][i];
    if(t) top[t]=top[x],dfs1(t);
    ;i<vec[x].size();i++)
     if(vec[x][i]!=fa[x]&&t!=vec[x][i])
       dfs1(vec[x][i]);
}
void dfs2(int x)
{
    ;i<vec[x].size();i++)
      if(fa[x]!=vec[x][i])
       dfs2(vec[x][i]),f[x]+=f[vec[x][i]];
}
int main()
{
    n=read();
    ;i<=n;i++)
     a[i]=read();
    ;i<n;i++)
    {
        x=read(),y=read();
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    deep[]=;
    dfs();
    dfs1();
    ;i<=n;i++)
    {
           x=a[i-];
           y=a[i];z=lca(x,y);
           f[x]++;f[fa[y]]++;
           f[z]--;f[fa[z]]--;
    }
    dfs2();
    ;i<=n;i++)
     printf("%d\n",f[i]);
    ;
}

松鼠的新家(lca)的更多相关文章

  1. [JLOI2014] 松鼠的新家 (lca/树上差分)

    [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...

  2. 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀请小熊维尼前来 ...

  3. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  4. 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1231  Solved: 620[Submit][Stat ...

  5. [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

    今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...

  6. 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

    [题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...

  7. [BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)

    题目传送门 题目描述: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  8. BZOJ 3631: [JLOI2014]松鼠的新家 树上差分 + LCA

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

  9. BZOJ 3631 【JLOI2014】 松鼠的新家

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

随机推荐

  1. phpExcel使用方法二

    require_once './phpexcel/PHPExcel.php'; // 首先创建一个新的对象 PHPExcel object $objPHPExcel = new PHPExcel(); ...

  2. 【windows】win7 sp1 系统语言中英文切换

    注:Windows 7 Ultimate and Windows 7 Enterprise (旗舰版和企业版) 可以直接在控制面板/地区和语言中修改显示语言,其他系统不行 进入网站下载相关的MUI包安 ...

  3. leetcode-9-basic-binary search

    278. First Bad Version You are a product manager and currently leading a team to develop a new produ ...

  4. JavaSE——final修饰符

    一.final 修饰变量,被final修饰的变量在被赋初始值之后,不能对它重新赋值 修饰实例变量,必须显示指定初始值,可以在三个位置指定初始值:         1.定义final实例变量时指定初始值 ...

  5. 在ionic项目中使用极光推送实现推送 & 服务器端代码

    ionic start -a jPushDemo -i com.lawxin.fengkong jpushdemo blank meteor add cordova:cn.jpush.phonegap ...

  6. 算法学习记录-排序——插入排序(Insertion Sort)

    插入排序: 在<算法导论>中是这样描述的 这是一个对少量元素进行排序的有效算法.插入排序的工作机理与打牌时候,整理手中的牌做法差不多. 在开始摸牌时,我们的左手是空的,牌面朝下放在桌子上. ...

  7. jenkins 之 Android 打包及上传至蒲公英

    准备条件 iMAC,非必须(如果是 安卓 和 苹果 可以在同一台电脑上打包则要 Mac OS 系统的电脑,如果是只是给安卓打包 windows 电脑也是可以的, window 下 需要把 ls 换成 ...

  8. 转:Generating PDFs from Web Pages on the Fly with jsPDF

    The Portable Document Format has been one the major innovations in the fields of desktop publishing ...

  9. Install Oracle 11G Release 2 (11.2) on Oracle Linux 7 (OEL7)

    Install Oracle 11G Release 2 (11.2) on Oracle Linux 7 (OEL7) This article presents how to install Or ...

  10. AtCoder Grand Contest 020

    A - Move and Win Time limit : 1sec / Memory limit : 512MB Score : 300 points Problem Statement A gam ...