「LuoguP3384」【模板】树链剖分
题目描述
如题,已知一棵包含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取模)
输入输出样例
说明
时空限制: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(重要的事情说三遍:记得取模)
题解
我也是会树剖的女人了!!!嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷
模板题嘛QAQ,也没什么好讲的
剖了之后,对于操作1和2,在求lca的过程中做
对于操作3和4,直接在dfn[x]和dfn[x]+siz[x]-1上搞事就星了
其实操作1和2可以用树上前缀和水水水水水水(不对要随时询问好像布星QAQ)
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN=2e5+;
int val[MAXN];//点权
//以下建原树
struct emm{
int e,f;
}b[*MAXN];
int h[MAXN];
int tot=;
void con(int x,int y)
{
b[++tot].f=h[x];
h[x]=tot;
b[tot].e=y;
b[++tot].f=h[y];
h[y]=tot;
b[tot].e=x;
return;
}
//第一遍dfs
int d[MAXN],fa[MAXN],top[MAXN],z[MAXN],siz[MAXN];
void dfs(int x)
{
siz[x]=;
top[x]=x;
int mac=,macc=-;
for(int i=h[x];i;i=b[i].f)
if(!d[b[i].e])
{
d[b[i].e]=d[x]+;
fa[b[i].e]=x;
dfs(b[i].e);
siz[x]+=siz[b[i].e];
if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
}
z[x]=mac;
top[mac]=x;
return;
}
//第二遍dfs
int q[MAXN],dfn[MAXN];
void dfss(int x)
{
q[++tot]=x;
dfn[x]=tot;
if(z[x])dfss(z[x]);
for(int i=h[x];i;i=b[i].f)
if(fa[b[i].e]==x&&b[i].e!=z[x])
dfss(b[i].e);
return;
}
//找top
int fitop(int x)
{
if(top[x]==x)return x;
return top[x]=fitop(top[x]);
}
//建树完成
int n,m,s;
long long mod;
//以下线段树
struct ahh{
int l,r;
long long v,laz;
}a[*MAXN];
void build(int i,int ll,int rr)
{
a[i].l=ll;
a[i].r=rr;
if(ll==rr){a[i].v=val[q[ll]];return;}
int mid=(ll+rr)>>;
build((i<<),ll,mid);
build(((i<<)|),mid+,rr);
a[i].v=a[(i<<)].v+a[((i<<)|)].v%mod;
return;
}
void add(int i,int ll,int rr,int k)
{
if(a[i].l==ll&&a[i].r==rr)
{a[i].laz+=k;return;}
a[i].v=(long long)a[i].v+(rr-ll+)*k%mod;
int mid=(a[i].l+a[i].r)>>;
if(rr<=mid)add((i<<),ll,rr,k);
else if(mid+<=ll)add(((i<<)|),ll,rr,k);
else {add((i<<),ll,mid,k);add(((i<<)|),mid+,rr,k);}
return;
}
void pushtag(int i)
{
if(!a[i].laz)return;
a[i].v=(long long)a[i].v+a[i].laz*(a[i].r-a[i].l+)%mod;
if(a[i].l==a[i].r){a[i].laz=;return;}
a[(i<<)].laz+=a[i].laz;
a[((i<<)|)].laz+=a[i].laz;
a[i].laz=;
return;
}
unsigned long long ans;
void find(int i,int ll,int rr)
{
pushtag(i);
if(a[i].l==ll&&a[i].r==rr){ans=(ans+a[i].v)%mod;return;}
int mid=(a[i].l+a[i].r)>>;
if(rr<=mid)find((i<<),ll,rr);
else if(ll>=mid+)find(((i<<)|),ll,rr);
else {find((i<<),ll,mid);find(((i<<)|),mid+,rr);}
return;
}
//
int main()
{
//freopen("a.in","r",stdin);
scanf("%d%d%d%lld",&n,&m,&s,&mod);
for(int i=;i<=n;++i)
scanf("%d",&val[i]);
for(int i=;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
con(x,y);
}
d[s]=;
dfs(s);
tot=;
dfss(s);
for(int i=;i<=n;++i)
top[i]=fitop(i);
build(,,n);
//run
for(int c=;c<=m;++c)
{
int opt;
scanf("%d",&opt);
if(opt==)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
//lca
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])
{
add(,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
else
{
add(,dfn[top[y]],dfn[y],z);
y=fa[top[y]];
}
}
if(d[x]>d[y])add(,dfn[y],dfn[x],z);
else add(,dfn[x],dfn[y],z);
}
else if(opt==)
{
int x,y;
scanf("%d%d",&x,&y);
ans=;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])
{
find(,dfn[top[x]],dfn[x]);
ans%=mod;
x=fa[top[x]];
}
else
{
find(,dfn[top[y]],dfn[y]);
ans%=mod;
y=fa[top[y]];
}
}
if(d[x]>d[y])find(,dfn[y],dfn[x]);
else find(,dfn[x],dfn[y]);
printf("%lld\n",ans%mod);
}
else if(opt==)
{
int x,z;
scanf("%d%d",&x,&z);
add(,dfn[x],dfn[x]+siz[x]-,z);
}
else
{
int x;
scanf("%d",&x);
ans=;
find(,dfn[x],dfn[x]+siz[x]-);
printf("%lld\n",ans%mod);
}
}
return ;
}
「LuoguP3384」【模板】树链剖分的更多相关文章
- 「POJ3237」Tree(树链剖分)
题意 给棵n个点的树.边有边权然后有三种操作 1.CHANGE i v 将编号为i的边权变为v 2.NEGATE a b 将a到b的所有边权变为相反数. 3.QUERY a b 查询a b路径的最大边 ...
- 「HNOI2015」开店(树链剖分, 主席树)
/* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...
- luoguP3384 [模板]树链剖分
luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- [洛谷P3384] [模板] 树链剖分
题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)
题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...
- 模板 树链剖分BFS版本
//点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...
- P3384 [模板] 树链剖分
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- 『题解』洛谷P3384 【模板】树链剖分
Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...
随机推荐
- GitHub中watch、star、fork的作用
star 的作用是收藏,目的是方便以后查找. watch 的作用是关注,目的是等作者更新的时候,你可以收到通知. fork 的作用是参与,目的是你增加新的内容,然后 Pull Request,把你的修 ...
- shell高级-----初识sed和gawk
sed编辑器 sed说明 sed是Linux下一款功能强大的非交互流式文本编辑器,可以对文本文件进行增.删.改.查等操作,支持按行.按字段.按正则匹配文本内容,灵活方便,特别适合于大文件的编辑. 替换 ...
- Hive入门及常用指令
基础命令show databases; # 查看某个数据库use 数据库; # 进入某个数据库show tables; # 展示所有表desc 表名; # 显示表结构show partitions 表 ...
- nsmutablestring 属性声明为copy程序崩溃了
obj.mutableStr = (NSMutableString *)[[NSMutableString alloc] initWithString:@"Hello"]; NSL ...
- String、StringBuffer和StringBuilder的差别
String.StringBuffer和StringBuilder的差别 1.String类是不可变类,即一旦一个String对象被创建后.包括这个对象中的字符序列是不可改变的 2.在字符串拼接的过程 ...
- 关于android分享(sharedsdk的简单使用)
老早就使用了.可是如今才写,惰性太大,如今改 如今做产品的话相信大家基本都做分享吧.一个是项目的需求须要,另一个是能够非常好的宣传自己的产品.其它的优点依据情况而论 事实上每一个平台都有它自己的文档, ...
- 【嵌入式Linux+ARM】GPIO操作
1.GPIO介绍 GPIO(general purpose i/o ports)意思为通用输入/输出端口,通俗的说就是一些引脚. 我们可以通过它们输出高低电平 或 读入引脚的状态. s3c2440中有 ...
- SolidEdge 如何绘制零件图的剖视图
1 点击检视-剖面,然后选择剖切面 2 比如要全剖,则绘制好方框之后点返回,选择方向. 选择剖切深度,然后预览即可 一个零件可以进行多次剖切
- VBA 把电信的电话费用表转换成部门电话费用明细表(图文)
今天同事要做一个这种工作.就是把电信发来的费用表,转换成按部门划分的电话费用表,100多部电话,假设一个个去核对,真还是须要些时间的.问题来了,有更好的方法么,我们来看一下. 电信公司给的费用明细是这 ...
- 翻翻git之---"有趣效果"的自己定义View EasyArcLoading
转载请注明出处:王亟亟的大牛之路 早上写了一个关于MD的文章,下午给编译器调了个色,感觉要上天了.所以为了试颜色就出了这篇文章,让大家一起瞎一下 好了废话不说.这一片给大家介绍一个当做Dialog作用 ...