P3258 [JLOI2014]松鼠的新家 树链剖分
这个题就是一道树剖板子题,就是每走一步就把所有的经过点加一就行了。还有,我的树剖板子没问题!!!谁知道为什么板子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]松鼠的新家 树链剖分的更多相关文章
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)
题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...
- BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )
裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...
- Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MB Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个 ...
- [JLOI2014]松鼠的新家-树链剖分
最开始的时候我在写线段树部分的时候还打了一个build,后来一想,打个球球大作战的build啊!!!有个锤子的用啊!!! #include<bits/stdc++.h> using nam ...
- BZOJ3631 松鼠的新家(树链剖分)
题目链接 松鼠的新家 差不多可以说是树链剖分的模板题了,直接维护即可. #include <bits/stdc++.h> using namespace std; #define REP( ...
- 【BZOJ3631】松鼠的新家 树链剖分
BZOJ3631 松鼠的新家 Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- P3285 松鼠的新家 (树链剖分)
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
- BZOJ - 3631 松鼠的新家 (树链剖分)
题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...
随机推荐
- Microsoft SQL Server 安全与权限
Microsoft SQL Server 安全与权限 登陆角色 计算机操作系统用户 --创建Windows身份验证用户 USE [master] GO CREATE LOGIN [计算机名称\计算机用 ...
- spring aop 内部调用问题解决
方法1: 基于 proxy 的 spring aop 带来的内部调用问题可以使用 AopContext.currentProxy() 强转为当前的再调用就可以解决了 例如: 错误用法:public A ...
- 汇编学习pushl, popl
- 洛谷——P3003 [USACO10DEC]苹果交货Apple Delivery
P3003 [USACO10DEC]苹果交货Apple Delivery 这题没什么可说的,跑两遍单源最短路就好了 $Spfa$过不了,要使用堆优化的$dijkstra$ 细节:1.必须使用优先队列+ ...
- Servlet过滤器的使用
Servlet过滤器的使用 制作人:全心全意 Servlet过滤器:Servlet过滤器与Servlet十分相似,但它具有拦截客户端请求的功能,Servlet过滤器可以改变请求中的内容,来满足实际开发 ...
- Linux文件/目录,权限相关
查看权限 命令 # ls -l filename 结果 -rw-r--r-- l root root 27 11-10 14:50 filename 解析: -rw-r--r-- --共10位 第1位 ...
- xfce 安装文泉驿字体
下载文泉驿字体 #拷贝字体到目录/usr/share/fonts/wqy#创建字体缓存 mkfontscale # 在当前目录下生成fonts.scale文件 mkfontdir # 在当前目录下生成 ...
- 洛谷 2213 [USACO14MAR]懒惰的牛The Lazy Cow_Sliver
[题解] 每个格子可以到达的区域是一个菱形,但是我们并不能快速的求和,所以我们可以把原来的草地旋转45度,用二维前缀和快速处理菱形的区域的和. #include<cstdio> #incl ...
- 洛谷 2173 BZOJ 2816 [ZJOI2012]网络
[题解] 明显的LCT模板题,c种颜色就开c棵LCT好了.. #include<cstdio> #include<algorithm> #define N 100010 #de ...
- Java MyBatis 插入数据库返回主键--insertSelective这样就不用每次到数据库里面查询了
insertSelective---Java MyBatis 插入数据库返回主键--insertSelective这样就不用每次到数据库里面查询了 https://www.cnblogs.com/xi ...