题目描述

如题,已知一棵包含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取模

输入输出样例

输入样例#1:
复制

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
输出样例#1: 复制

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(重要的事情说三遍:记得取模)

题解

我也是会树剖的女人了!!!嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷

模板题嘛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」【模板】树链剖分的更多相关文章

  1. 「POJ3237」Tree(树链剖分)

    题意 给棵n个点的树.边有边权然后有三种操作 1.CHANGE i v 将编号为i的边权变为v 2.NEGATE a b 将a到b的所有边权变为相反数. 3.QUERY a b 查询a b路径的最大边 ...

  2. 「HNOI2015」开店(树链剖分, 主席树)

    /* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...

  3. luoguP3384 [模板]树链剖分

    luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...

  4. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  5. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  6. loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

    题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...

  7. 模板 树链剖分BFS版本

    //点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...

  8. P3384 [模板] 树链剖分

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...

  9. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

  10. 『题解』洛谷P3384 【模板】树链剖分

    Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...

随机推荐

  1. mybatis注解@selectKey对于db2数据库的使用

    在新增时返回当前新增的主键. 数据库:DB2 用的是mybatis的@selectKey 代码: @InsertProvider(type = Test.class,method="inse ...

  2. Flink的安装配置

    一. Flink的下载 安装包下载地址:http://flink.apache.org/downloads.html  ,选择对应Hadoop的Flink版本下载 [admin@node21 soft ...

  3. DELPHI方法注释的标准写法

    /// <summary> /// 查询数据 /// </summary> /// <param name="accountno">帐套号< ...

  4. Camtasia Studio录制屏幕字迹不清晰的原因

    Camtasia Studio这是一个很优秀的屏幕录像软件,功能强大且录制效果出色,支持众多格式输出: 之前一直用它录制视频的都很正常,但这次换系统后再重新安装后录制视频时,发现输出的视频画质不佳,文 ...

  5. android开发教程之使用线程实现视图平滑滚动示例

    最近一直想做下拉刷新的效果,琢磨了好久,才走到通过onTouch方法把整个视图往下拉的步骤,接下来就是能拉下来,松开手要能滑回去啊.网上看了好久,没有找到详细的下拉刷新的例子,只有自己慢慢琢磨了.昨天 ...

  6. ElasticSearch集群本机搭建

    ElasticSearch集群本机搭建 elasticsearch elasticsearch -Ehttp.port=8200 -Epath.data=node2 elasticsearch -Eh ...

  7. PHP生成excel(3)

    这一节主要是设置背景颜色.边框.字体大小.表格宽度 效果图 代码如下 <?php header("Content-Type:text/html;charset=utf-8") ...

  8. C++ string 实现大整数相加减

    随意两个大整数的加减算法.可自己主动推断正负号.代码例如以下: #include <iostream> #include <vector> #include <cstri ...

  9. java设计模式----真实世界的模式

    设计模式的定义: 模式是在某情境下,针对某问题的某种解决方案 反模式: 告诉你如何采用一个不好的解决方案解决一个问题 要点: 1.让设计模式自然而然地出现在你的设计中,而不是为了使用而使用 2.设计模 ...

  10. Linq To Sql进阶系列(六)用object的动态查询与保存log篇

    动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...