洛谷P3384 【模板】树链剖分
题目描述
如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:
操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z
操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和
操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z
操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和
输入输出格式
输入格式:
第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。
接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。
接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)
接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:
操作1: 1 x y z
操作2: 2 x y
操作3: 3 x z
操作4: 4 x
输出格式:
输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)
输入输出样例
5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
2
21
说明
时空限制:1s,128M
数据规模:
对于30%的数据: N≤10,M≤10
对于70%的数据: N≤10^3,M≤10^3
对于100%的数据: N≤10^5,M≤10^5
( 其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233 )
样例说明:
树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100007
using namespace std;
long long read()
{
long long x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
int n,m,num,root,p,opt,x,y,z,cnt;
int head[maxn*],a[maxn],son[maxn],fa[maxn],deep[maxn],size[maxn],top[maxn],pos[maxn],data[maxn],in[maxn],out[maxn];
struct node
{
int v,nxt;
} e[maxn];
void add(int u,int v)
{
e[++num].v=v;
e[num].nxt=head[u];
head[u]=num;
e[++num].v=u;
e[num].nxt=head[v];
head[v]=num;
}
struct NODE
{
int l,r,sum,flag;
} tree[maxn*];
void dfs(int now)
{
size[now]=;
for(int i=head[now]; i; i=e[i].nxt)
if(fa[now]!=e[i].v)
{
fa[e[i].v]=now;
deep[e[i].v]=deep[now] + ;
dfs(e[i].v);
size[now]+=size[e[i].v];
if(size[son[now]]<size[e[i].v])
son[now]=e[i].v;
}
}
void DFS(int now,int num)
{
top[now]=num;
pos[now]=++cnt;
in[now]=cnt;
data[cnt]=a[now];
if(son[now])
DFS(son[now],num);
for(int i=head[now]; i; i=e[i].nxt)
if(fa[now]!=e[i].v&&e[i].v!=son[now])
DFS(e[i].v,e[i].v);
out[now]=cnt;
}
void build(int now,int l,int r)
{
tree[now].l=l;
tree[now].r=r;
tree[now].flag=;
if(l==r)
{
tree[now].sum=data[l];
return ;
}
int mid=(l+r)>>;
build(now<<,l,mid);
build(now<<|,mid+,r);
tree[now].sum=tree[now<<].sum+tree[now<<|].sum;
}
void down(int now)
{
if(tree[now].l==tree[now].r)
{
tree[now].flag=;
return ;
}
tree[now<<].flag+=tree[now].flag;
tree[now<<|].flag+=tree[now].flag;
tree[now<<].sum=(tree[now<<].sum+tree[now].flag*(tree[now<<].r-tree[now<<].l+))%p;
tree[now<<|].sum=(tree[now<<|].sum+tree[now].flag*(tree[now<<|].r-tree[now<<|].l+))%p;
tree[now].flag=;
}
void change(int now,int l,int r,int f)
{
while(tree[now].flag)
down(now);
if(tree[now].l>r||tree[now].r<l)
return ;
if(tree[now].l>=l&&tree[now].r<=r)
{
tree[now].flag=f;
(tree[now].sum+=f*(tree[now].r-tree[now].l+))%=p;
return ;
}
change(now<<,l,r,f);
change(now<<|,l,r,f);
tree[now].sum=(tree[now<<].sum+tree[now<<|].sum)%p;
}
int query(int now,int l,int r)
{
while(tree[now].flag) down(now);
if(tree[now].l>r||tree[now].r<l)
return ;
if(tree[now].l>=l&&tree[now].r<=r)
return tree[now].sum;
return (query(now<<,l,r)+query(now<<|,l,r))%p;
}
void add1()
{
x=read(),y=read(),z=read(),z%=p;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
change(,pos[top[x]],pos[x],z);
x=fa[top[x]];
}
if(deep[x]<deep[y])
swap(x,y);
change(,pos[y],pos[x],z);
}
void add2()
{
x=read(),z=read(),z%=p;
change(,in[x],out[x],z);
}
void query1()
{
x=read(),y=read();
int ans=;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
ans=(ans+query(,pos[top[x]],pos[x]))%p;
x=fa[top[x]];
}
if(deep[x]<deep[y])
swap(x,y);
(ans+=query(,pos[y],pos[x]))%=p;
printf("%d\n",ans);
}
void query2()
{
x=read();
int ans=;
(ans=query(,in[x],out[x]))%=p;
printf("%d\n",ans);
}
int main()
{
n=read(),m=read(),root=read(),p=read();
for(int i=; i<=n; ++i)
a[i]=read(),a[i]%=p;
for(int i=,a,b; i<n; ++i)
a=read(),b=read(),add(a,b);
dfs(root);
DFS(root,root);
build(,,n);
while(m--)
{
opt=read();
if(opt==)
add1();
else if(opt==)
add2();
else if(opt==)
query1();
else
query2();
}
return ;
}
洛谷P3384 【模板】树链剖分的更多相关文章
- [洛谷P3384] [模板] 树链剖分
题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- 洛谷 P4114 Qtree1 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...
- 洛谷.4114.Qtree1(树链剖分)
题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...
- 洛谷3384&bzoj1036树链剖分
值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...
- P3384 [模板] 树链剖分
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...
- luoguP3384 [模板]树链剖分
luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...
- 【Luogu P3384】树链剖分模板
树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...
- 模板 树链剖分BFS版本
//点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...
随机推荐
- xhr是什么文件类型?
xhr:XMLHttpRequest在后台与服务器交换数据,这意味着可以在不加载整个网页的情况下,对网页某部分的内容进行更新. 是Ajax的一种用法,而Ajax并不是一门语言,只是一种不需要加载整个网 ...
- H+ 显示并激活menuTab 根据tabName
//注:在contabs.js文件中 $(function () { }); 方法外 加入//注: data-name="' + menuName + '" 这句是加入的自定义属性 ...
- Jackson 解析json数据之忽略解析字段注解@JsonIgnoreProperties
转自:http://blog.csdn.net/ngl272/article/details/70217104 以前解析json用的惯的就是Google的gson了,用惯了基本就用它了,一直也没发现什 ...
- Spring的两种代理方式:JDK动态代理和CGLIB动态代理
代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对 ...
- C#学习笔记(36)——事件传值(非常牛逼!)
说明(2018-4-9 23:01:20): 1. 这个真的想了很久,从晚上八点半写完上一篇博客,一直想到现在11点,以为没有办法实现了,结果看到一篇CSDN的文章,虽然没有看明白,但是看到一行代码后 ...
- error $GOPATH: no library found in $GOPATH: rdkafka
安装confluent-kafka-go出错时,请使用brew安装pkg-config,手动go get安装的pkg-config还不行... 错误提示: go get -u github.com/c ...
- Altium designer软件如何设计原理图库封装图库以及交互式布局
欢迎大家关注http://www.raymontec.com(个人专博) Altium Designer学习—认识界面以及PCB设计整体要求 http://www.raymontec.com/alti ...
- 解决vscode无法安装golang相关插件的问题 - 即无法直连golang.org的问题
喜欢挂vpn或者代理的请无视本文. 其实golang.org上的插件在github.com上都有镜像,直接 git clone https://github.com/golang/tools git ...
- C# 获取对象 大小 Marshal.SizeOf (sizeof 只能在不安全的上下文中使用)
C# 能否获取一个对象所占内存的大小? 今日,在项目重构的时候忽然想到一个问题,一个类哪些成员的增加,会影响一个类所占内存的大小?C#有没有办法知道一个对象占多少内存呢? 第一个问题:很快想到是类的非 ...
- unity3d IL2CPP for android
unity3d 使用IL2Cpp导出android工程报以下错误解决方法 重点是这块 “”System.Reflection.TargetInvocationException: ���õ�Ŀ�귢�� ...