这个题就是一道树剖板子题,就是每走一步就把所有的经过点加一就行了。还有,我的树剖板子没问题!!!谁知道为什么板子T3个点!我不管了!反正这道题正常写A了。

题干:

题目描述

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

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

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

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
输入输出格式
输入格式:
第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
输出格式:
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
输入输出样例
输入样例#: 复制 输出样例#: 复制 说明
<= n <=

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
const int N = ;
struct node
{
int l,r,nxt;
}a[ * N];
int n,len = ,lst[N];
int A[N],tree[ * N];
void add(int x,int y)
{
a[++len].l = x;
a[len].r = y;
a[len].nxt = lst[x];
lst[x] = len;
}
int f[N],dep[N],son[N],siz[N],id[N],rk[N];
int tp[N],cnt = ,lazy[ * N],vis[N];
void dfs1(int u,int fa,int depth)
{
f[u] = fa;
siz[u] = ;
dep[u] = depth;
for(int k = lst[u];k;k = a[k].nxt)
{
int y = a[k].r;
if(y == fa) continue;
dfs1(y,u,depth + );
siz[u] += siz[y];
if(!son[u] || siz[son[u]] < siz[y])
son[u] = y;
}
}
void dfs2(int u,int t)
{
vis[u] = ;
tp[u] = t;
id[u] = ++cnt;
rk[cnt] = u;
if(!son[u])
return;
dfs2(son[u],t);
for(int k = lst[u];k;k = a[k].nxt)
{
int y = a[k].r;
if(y == son[u] || y == f[u] || vis[y] == ) continue;
dfs2(y,y);
}
}
void push_down(int o,int l,int r)
{
if(lazy[o] != )
{
int mid = (l + r) >> ;
tree[o << ] += (mid - l + ) * lazy[o];
tree[o << | ] += (r - mid) * lazy[o];
lazy[o << ] += lazy[o];
lazy[o << | ] += lazy[o];
lazy[o] = ;
}
}
void update(int o,int l,int r,int x,int y)
{
int mid = (l + r) >> ;
if(l == x && r == y)
{
tree[o] += (r - l + );
lazy[o] += ;
return;
}
push_down(o,l,r);
if(mid >= y)
update(o << ,l,mid,x,y);
else if(mid < x)
update(o << | ,mid + ,r,x,y);
else
{
update(o << ,l,mid,x,mid);
update(o << | ,mid + ,r,mid + ,y);
}
tree[o] = tree[o << ] + tree[o << | ];
}
void update2(int x,int y)
{
while(tp[x] != tp[y])
{
if(dep[tp[x]] < dep[tp[y]]) swap(x,y);
update(,,n,id[tp[x]],id[x]);
x = f[tp[x]];
}
if(id[x] > id[y]) swap(x,y);
update(,,n,id[x],id[y]);
}
int query(int o,int l,int r,int id)
{
if(l == r)
return tree[o];
push_down(o,l,r);
int mid = (l + r) >> ;
if(id <= mid)
return query(o << ,l,mid,id);
else
return query(o << | ,mid + ,r,id);
}
int main()
{
read(n);
duke(i,,n)
read(A[i]);
duke(i,,n - )
{
int x,y;
read(x);read(y);
add(x,y);
add(y,x);
}
dfs1(,,);
dfs2(,);
/*duke(i,1,n)
printf("%d %d\n",id[i],tp[i]);*/
// printf("QAQ\n");
duke(i,,n - )
update2(A[i],A[i + ]);
duke(i,,n)
{
int p = query(,,n,id[i]);
if(A[] != i)
p -= ;
printf("%d\n",p);
}
return ;
}

顺便附赠树剖板子:

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
const int N = ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
struct edge
{
int nxt,r;
} e[ * N];
int n,m,r,cnt;
int a[N],lst[N],p;
int f[N],d[N],siz[N],son[N],rk[N];
int top[N],id[N],tree[ * N];
int lazy[ * N],len = ;
//id新编号dfs序
void add(int x,int y)
{
e[++len].nxt = lst[x];
e[len].r = y;
lst[x] = len;
} void dfs1(int u,int fa,int depth)
{
f[u] = fa;
d[u] = depth;
siz[u] = ;
for(int k = lst[u];k;k = e[k].nxt)
{
int y = e[k].r;
if(y == fa)
continue;
dfs1(y,u,depth + );
siz[u] += siz[y];
if(siz[y] > siz[son[u]] || !son[u])
{
son[u] = y;
}
}
} void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
rk[cnt] = u;
if(!son[u])
return;
dfs2(son[u],t);
for(int k = lst[u];k;k = e[k].nxt)
{
int y = e[k].r;
if(y != son[u] && y != f[u])
dfs2(y,y);
}
} void push_down(int o,int l,int r)
{
if(lazy[o])
{
lazy[o << ] += lazy[o];
lazy[o << ] %= p;
lazy[o << | ] += lazy[o];
lazy[o << | ] %= p;
int len = (r - l + );
tree[o << ] += lazy[o] * (len - (len >> ));
tree[o << | ] += lazy[o] * (len >> );
tree[o << ] %= p;
tree[o << | ] %= p;
lazy[o] = ;
}
} void build(int o,int l,int r)
{
if(l == r)
{
tree[o] = a[rk[l]];
tree[o] %= p;
return;
}
int mid = (l + r) >> ;
build(o << ,l,mid);
build(o << | ,mid + ,r);
tree[o] = tree[o << ] + tree[o << | ];
tree[o] %= p;
} void up_num(int o,int l,int r,int x,int y,int w)
{
if(l == x && r == y)
{
tree[o] += w * (l - r + );
tree[o] %= p;
lazy[o] += w;
lazy[o] %= p;
return;
}
push_down(o,l,r);
int mid = (l + r) >> ;
if(mid < x)
up_num(o << | ,mid + ,r,x,y,w);
else if(mid >= y)
up_num(o << ,l,mid,x,y,w);
else
{
up_num(o << ,l,mid,x,mid,w);
up_num(o << | ,mid + ,r,mid + ,y,w);
}
tree[o] = tree[o << ] + tree[o << | ];
tree[o] %= p;
} int query(int o,int l,int r,int x,int y)
{
if(l == r && x == y)
{
return tree[o];
}
push_down(o,l,r);
int mid = (l + r) >> ;
if(mid >= y)
return query(o << ,l,mid,x,y);
else if(mid < x)
return query(o << | ,mid + ,r,x,y);
else
{
return (query(o << ,l,mid,x,mid) + query(o << | ,mid + ,r,mid + ,y)) % p;
}
} int pathquery(int x,int y)
{
int ans = ;
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]])
swap(x,y);
ans += query(,,n,id[top[x]],id[x]);
ans %= p;
x = f[top[x]];
}
if(d[x] > d[y])
swap(x,y);
ans += query(,,n,id[x],id[y]);
ans %= p;
return ans;
} void pathupdate(int x,int y,int c)
{
// int fx = top[x],fy = top[y];
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]])
swap(x,y);
up_num(,,n,id[top[x]],id[x],c);
x = f[top[x]];
// update(id[x])
}
if(d[x] > d[y])
swap(x,y);
up_num(,,n,id[x],id[y],c);
}
int main()
{
read(n);read(m);read(r);read(p);
duke(i,,n)
read(a[i]);
duke(i,,n - )
{
int x,y;
read(x);read(y);
add(x,y);
add(y,x);
}
cnt = ;
dfs1(r,,);
dfs2(r,r);
cnt = ;
build(,,n);
duke(i,,m)
{
int op,x,y,z;
read(op);
if(op == )
{
read(x);read(y);read(z);
pathupdate(x,y,z);
}
else if(op == )
{
read(x);read(y);
printf("%d\n",pathquery(x,y));
}
else if(op == )
{
read(x);read(z);
// cout<<x<<endl;
up_num(,,n,id[x],id[x] + siz[x] - ,z);
}
else
{
read(x);
printf("%d\n",query(,,n,id[x],id[x] + siz[x] - ));
}
}
return ;
}
/*
5 2 24
3 7 8 0
2
5
1
1
4 2
2 2
5
5 1 3
1 3
*/

P3258 [JLOI2014]松鼠的新家 树链剖分的更多相关文章

  1. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  2. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

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

  3. BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )

    裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...

  4. Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MB Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个 ...

  5. [JLOI2014]松鼠的新家-树链剖分

    最开始的时候我在写线段树部分的时候还打了一个build,后来一想,打个球球大作战的build啊!!!有个锤子的用啊!!! #include<bits/stdc++.h> using nam ...

  6. BZOJ3631 松鼠的新家(树链剖分)

    题目链接 松鼠的新家 差不多可以说是树链剖分的模板题了,直接维护即可. #include <bits/stdc++.h> using namespace std; #define REP( ...

  7. 【BZOJ3631】松鼠的新家 树链剖分

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

  8. P3285 松鼠的新家 (树链剖分)

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

  9. BZOJ - 3631 松鼠的新家 (树链剖分)

    题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...

随机推荐

  1. jQuery鼠标划入划出

    今天来简单的谈谈jQuery的一个划入划出的方法,.首先划入划出能想到的东西有哪些呢,. 1:hover 2:mouseenter/mouseleave 3:mouseover/mouseout. 一 ...

  2. java的标识符和关键词

    1.1.1 标识符   可以简单的理解为一个名字.在Java中,我们需要标识代码的很多元素,包括类名.方法.字段.变量.包名等.我们选择的名称就称为标识符,并且遵循以下规则: 标识符可以由字母.数字. ...

  3. spring思想分析

    摘要: EveryBody in the world should learn how to program a computer...because it teaches you how to th ...

  4. Linux System

    Linux System linux 是一个功能强大的操作系统,同时它是一个自由软件,是免费的.源代码开放的,编制它的目的是建立不受任何商品化软件版权制约的.全世界都能自由使用的UNIX兼容产品.各种 ...

  5. [转载] kprobe原理解析(一)

    From: https://www.cnblogs.com/honpey/p/4575928.html kprobe原理解析(一) kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工 ...

  6. linux shell学习笔记二---自定义函数(定义、返回值、变量作用域)介绍

    linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.下面说说它的定义方法,以及调用需要注意那些事项. 一.定义shell函数(define function) 语法: [ f ...

  7. Extjs中Store小总结

    http://blog.csdn.net/without0815/article/details/7798170 1.什么是store? Store类似于一个本地仓库(即数据存储器),包括有 Arra ...

  8. HDU-4705 Y(思维+dfs树)

    Input 4 1 2 1 3 1 4 Output 1 题意:给你一颗树,选择一个三个点构成的集合,使得这三个点不在一条直线上(意思就是 从一个点出发,用一条不回头的线不能将这三个点连起来)问一共有 ...

  9. keep

    简介 什么是keepalived呢?keepalived是实现高可用的一种轻量级的技术手段,主要用来防止单点故障(单点故障是指一旦某一点出现故障就会导致整个系统架构的不可用)的发生.之所以说keepa ...

  10. Win32编程API 基础篇 -- 2.一个简单的窗口 根据英文教程翻译

    一个简单的窗口 例子:简单的窗口 有时人们在IRC提问,”我应该怎样制作一个窗口”...嗯,这恐怕不是完全这么简单好回答!其实这并不难一旦你明白你在做什么,但在你得到一个可展示的窗口之前还有一些事情需 ...