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

    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

    【思路】

    倍增/树链剖分 + 树上差分
    很有意思很有意思的一道题目
    会了树上差分几乎就是一个板子题
    不,是两个板子题
    倍增/树链剖分板子 + 树上差分板子
    先dfs出这棵树每个点的深度和他跳2^n之后会跳到哪一个点
    然后按照题目给出的到达房间的顺序
    (a_1)(a_2)的LCA, (a_2)(a_3) 的LCA……
    然后运用树上差分
    (a_i)(a_i+1) 的差分数组都加上1,
    然后将LCA和LCA夫妻的差分数组都减去1

    最后一个递归递归出每个店的值
    输出就好了
    注意:
    这里有n-1个点作为了起点也作为了终点
    所以重复了1次
    判断一下重复过的在输出的时候顺手减去1就好了

    【完整代码】

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    const int Max = 300005;
    struct node
    {
    	int y;
    	int ne;
    }s[Max << 1];
    int a[Max];
    int depth[Max];
    int fa[Max][23];
    int head[Max];
    int sum = 0;
    int c[Max];
    int ans[Max];
    
    void add(int x,int y)
    {
    	s[++ sum].y = y;
    	s[sum].ne = head[x];
    	head[x] = sum;
    	
    	s[++ sum].y = x;
    	s[sum].ne = head[y];
    	head[y] = sum;
    }
    
    void dfs(int f,int fath)
    {
    	depth[f] = depth[fath] + 1;
    	fa[f][0] = fath;
    	for(register int i = 1;(1 << i) <= depth[f];++ i)
    		fa[f][i] = fa[fa[f][i - 1]][i - 1];
    	for(int i = head[f];i != 0;i = s[i].ne)
    		if(s[i].y != fath)
    			dfs(s[i].y,f);
    }
    
    int lca(int x,int y)
    {
    	if(depth[x] < depth[y])swap(x,y);
    	for(register int i = 22;i >= 0;i --)
    		if(depth[fa[x][i]] >= depth[y])
    			x = fa[x][i];
    	if(x == y)return x;
    	for(register int i = 22;i >= 0;i --)
    		if(fa[x][i] != fa[y][i])
    			x = fa[x][i],y = fa[y][i];
    	return fa[x][0];
    }
    
    /*
    void doit(int x)
    {
    	ans[x] = c[x];
    	while(fa[x][0] != 0)
    	{
    		ans[fa[x][0]] += ans[x] + a[fa[x][0]];
    		x = fa[x][0];
    	}
    }
    
    void search(int x)
    {
    	int js = 0;
    	for(register int i = head[x];i != 0;i = s[i].ne)
    	{
    		int qwq = s[i].y;
    		if(qwq != fa[x][0])
    		{
    			js ++;
    			ans[qwq] = ans[x] + c[qwq];
    			search(qwq);
    		}
    	}
    	if(js == 0)
    		doit(x);
    }
    */
    
    int search(int x)
    {
    	ans[x] = c[x];
    	for(register int i = head[x];i != 0;i = s[i].ne)
    	{
    		int qwq = s[i].y;
    		if(qwq != fa[x][0])
    			ans[x] += search(qwq);
    	}
    	return ans[x];
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	freopen("1.out","w",stdout);
    	int n;
    	cin >> n;
    	int x,y;
    	for(register int i = 1;i <= n;++ i)
    		cin >> a[i];
    	for(register int i = 1;i < n;++ i)
    		cin >> x >> y,add(x,y);
    	dfs(1,0);
    	//fa[1][0] = 1;
    	for(register int i = 1;i < n;++ i)
    	{
    		int LCA = lca(a[i],a[i + 1]);
    		c[LCA] -= 1;c[fa[LCA][0]] -= 1;
    		c[a[i]] ++;c[a[i + 1]] ++;
    	}
    	/*
    	for(int i = 1;i <= n;++ i)
    		cout << c[i] << endl;
    	*/
    	int acioi = search(1);
    	for(register int i = 1;i <= n;++ i)
    	{
    		if(i == a[1])
    			cout << ans[i] << endl;
    		else
    			cout << ans[i] - 1<< endl;
    	}
    	return 0;
    
  • 相关阅读:
    SaltStack 配置SLS过程
    Python 正则表达式
    Python 矩阵的旋转
    SaltStack 远程执行
    SaltStack 配置管理
    SaltStack
    Python 装饰器
    Python 生产者和消费者模型
    Python 迭代器和生成器
    Python json模块
  • 原文地址:https://www.cnblogs.com/acioi/p/11642664.html
Copyright © 2011-2022 走看看