省选被暴虐,成功爆0。。。顺便ditoly差点全省总分Rank1 orz.....

于是开始赶进度学新算法。。。。

然后决定开始学习树剖orz。。。

发现树剖很好用啊!!!!

然后做了模板题

题目就是给你一棵树,然后每次操作是查询或者增加一条树上2点路径/子树的值。

解题思路:都说了是树剖模板题,所以就要写树剖啊,然后用线段树维护。。。然后考虑多存储一下子树在线段树上的区间,就可以解决了。

期望时间效率\( O( m \log \log^{2} n )\).最坏时间复杂度: \( O( m \log^{2} n )\).

然后贴个版吧。。。

#include <stdio.h>
#define MN (1<<17)
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
#define v edge[i].to
#define Mn 100005
struct zxy{int to,nxt;}edge[Mn<<];
int mark[MN<<],sum[MN<<],n,son[Mn],head[Mn],top[Mn],siz[Mn],val[Mn],pos[Mn],fa[Mn],rpos[Mn],dep[Mn],mod,cnt,dfsn,q,root;
inline int in(){
int x=,f=; char ch=getchar();
while(ch<''||ch>'') f=ch=='-'?-:,ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x*f;
}
inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;}
inline void dfs1(int u,int f,int d){
fa[u]=f,dep[u]=d,siz[u]=;
for (register int i=head[u]; i; i=edge[i].nxt)
if (v!=f){
dfs1(v,u,d+);siz[u]+=siz[v];
if (siz[v]>siz[son[u]]) son[u]=v;
}
}
inline void dfs2(int u,int tp){
top[u]=tp;pos[u]=(++dfsn);if (son[u]) dfs2(son[u],tp);
for (register int i=head[u]; i; i=edge[i].nxt)
if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
rpos[u]=dfsn;
}
inline void pushdown(int k,int l,int r){
if (l==r||mark[k]==) return;
register int length=r-l+;
mark[ls]+=mark[k];mark[ls]%=mod;
mark[rs]+=mark[k];mark[rs]%=mod;
sum[ls]+=(1ll*((length-(length>>))%mod)*mark[k])%mod;sum[ls]%=mod;
sum[rs]+=(1ll*((length>>)%mod)*mark[k])%mod;sum[rs]%=mod;mark[k]=;
}
inline void combine(int k){sum[k]=sum[ls]+sum[rs];sum[k]%=mod;}
inline void update(int l,int r,int a,int b,int k,int ad){
if (a<=l&&r<=b){
mark[k]+=ad;mark[k]%=mod;
sum[k]+=(1ll*((r-l+)%mod)*ad)%mod;sum[k]%=mod;
return;
}pushdown(k,l,r);
if (a<=mid) update(l,mid,a,b,ls,ad);
if (b>mid) update(mid+,r,a,b,rs,ad);
combine(k);
}
inline int query(int l,int r,int a,int b,int k){
if (l==a&&r==b) return sum[k];pushdown(k,l,r);
if (b<=mid) return query(l,mid,a,b,ls);
if (a>mid) return query(mid+,r,a,b,rs);
return (1ll*query(l,mid,a,mid,ls)+query(mid+,r,mid+,b,rs))%mod;
}
inline void Mupdate(int x,int y,int ad){
while(top[x]!=top[y])
if (dep[top[x]]>dep[top[y]]) update(,n,pos[top[x]],pos[x],,ad),x=fa[top[x]];
else update(,n,pos[top[y]],pos[y],,ad),y=fa[top[y]];
if (dep[x]<dep[y]) update(,n,pos[x],pos[y],,ad);
else update(,n,pos[y],pos[x],,ad);
}
inline int Mquery(int x,int y){
register int res=;
while(top[x]!=top[y])
if (dep[top[x]]>dep[top[y]])
res=(1ll*res+query(,n,pos[top[x]],pos[x],))%mod,x=fa[top[x]];
else res=(1ll*res+query(,n,pos[top[y]],pos[y],))%mod,y=fa[top[y]];
if (dep[x]<dep[y]) res=(1ll*res+query(,n,pos[x],pos[y],))%mod;
else res=(1ll*res+query(,n,pos[y],pos[x],))%mod;return res;
}
void init(){
n=in(),q=in(),root=in(),mod=in();
for (register int i=; i<=n; ++i) val[i]=in(),val[i]%=mod;
for (register int i=; i<n; ++i){
register int x=in(),y=in();
ins(x,y);ins(y,x);
}dfs1(root,root,);dfs2(root,root);
for (register int i=; i<=n; ++i) update(,n,pos[i],pos[i],,val[i]);
}
void solve(){
while(q--){
register int op=in();
if (op&){
if (op==){
register int x=in(),y=in(),ad=in(); ad%=mod;
Mupdate(x,y,ad);
}else{
register int x=in(),ad=in(); ad%=mod;
update(,n,pos[x],rpos[x],,ad);
}
}
else{
if (op==){
register int x=in(),y=in();
printf("%d\n",Mquery(x,y));
}else{
register int x=in();
printf("%d\n",query(,n,pos[x],rpos[x],));
}
}
}
}
int main(){init();solve();}

【luogu3384】【模板】树链剖分的更多相关文章

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

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

  2. luoguP3384 [模板]树链剖分

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

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

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

  4. 模板 树链剖分BFS版本

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

  5. P3384 [模板] 树链剖分

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

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

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

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

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

  8. luogu3384 【模板】树链剖分

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

  9. luogu3384 /// 树链剖分+线段树模板

    题目大意: https://www.luogu.org/problemnew/show/P3384 树链剖分的讲解 两个dfs() 修改 查询 很详细很好理解 https://www.cnblogs. ...

  10. P3384 【模板】树链剖分

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

随机推荐

  1. alpha-咸鱼冲刺day8

    一,合照 emmmmm.自然还是没有的. 二,项目燃尽图 三,项目进展 正在进行页面整合.然后还有注册跟登陆的功能完善-- 四,问题困难 数据流程大概是搞定了.不过语法不是很熟悉,然后还有各种判定. ...

  2. beta冲刺计划安排

    经过紧张的Alpha阶段,很多组已经从完全不熟悉语言和环境,到现在能够实现初步的功能.下一阶段即将加快编码进度,完成系统功能.强化软件工程的体会. 凡事预则立,在Beta开始前,以小组为单位,在敏捷冲 ...

  3. 利用python 创建XML文件

    #coding=utf-8 from xml.etree import ElementTree import pdb def printNodeInfo(node): #node.tag 标签名称 # ...

  4. Beta冲刺Day4

    项目进展 李明皇 今天解决的进度 因服务器端未完成登录态维护,故无法进行前后端联动. 明天安排 前后端联动调试 林翔 今天解决的进度 因上课和实验室事务未完成登录态维护 明天安排 完成登录态维护 孙敏 ...

  5. Apache的配置httpd.conf文件配置

    (1) 基本配置: ServerRoot "/mnt/software/apache2" #你的apache软件安装的位置.其它指定的目录如果没有指定绝对路径,则目录是相对于该目录 ...

  6. 《高级软件测试》11.14.安装和运行Jira

    今日任务完成情况如下: 小段:研究Jira在Linux的安装教程 小费:尝试在Ubuntu下安装Jira 小高:查阅了关于Jira软件的介绍和安装教程,下载准备明天安装,并学习使用 小王:注册Jira ...

  7. day-5 python协程与I/O编程深入浅出

    基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1.  什么是协程(以下内容来自维基百 ...

  8. Python基础学习篇章二

    一. Python如何运行程序 1. 在交互模式下编写代码 最简单的运行Python程序的方法是在Python交互命令行中输入程序.当然有很多方法可以开始这样的命令行,比如IDE,系统终端.如果你已经 ...

  9. EasyUI datagrid 使用小结

    用了 EasyUI 框架一段时间了,这个前端框架用起来还是挺方便的,也有很多现成的控件,看看官方文档应该还是能比较快用起来的. 在这里记录一下一些常用的控件的方法,遇到过的bug或者当初耗了一点时间来 ...

  10. Tomcat性能优化及JVM内存工作原理

    Java性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收,下面会重点介绍这方面) 代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容如下: 1. ...