题目描述

如题,已知一棵包含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<=1000,M<=1000

对于100%的数据:N<=100000,M<=100000

(其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233)

样例说明:

树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)


My Solution

哪来的什么solution

因为这题快颓了week了

统计:2/29   AC!!!

为什么我之前要用树状数组嘞

向unsigned大佬低头    orz

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std; typedef long long ll; inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} inline ll rea(){
char ch;
ll re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct edge{
int to,next;
edge(int to=,int next=):
to(to),next(next){}
}; struct Segment_Tree{
int l,r;
ll sum,tag;
}; const int maxn=; int cnt,n,m,root;
ll mod;
edge edges[maxn<<];
Segment_Tree tre[maxn<<];
int head[maxn],top[maxn],dep[maxn],fat[maxn],id[maxn],id_[maxn],son[maxn],siz[maxn];
int data[maxn]; inline void add_edge(int from,int to){
edges[++cnt]=edge(to,head[from]); head[from]=cnt;
edges[++cnt]=edge(from,head[to]); head[to]=cnt;
} void init(){
n=read(); m=read(); root=read(); mod=rea();
for(int i=;i<=n;i++)
data[i]=read();
int from,to;
cnt=;
for(int i=;i<n;i++){
from=read(); to=read();
add_edge(from,to);
}
} void dfs_1(int x,int fa){
fat[x]=fa;
siz[x]=;
dep[x]=dep[fa]+;
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa){
dfs_1(edges[ee].to,x);
siz[x]+=siz[edges[ee].to];
if(!son[x]||siz[edges[ee].to]>siz[son[x]])
son[x]=edges[ee].to;
}
} void dfs_2(int x,int fa){
if(!son[x]) return;
top[son[x]]=top[x];
id[son[x]]=++cnt;
id_[cnt]=son[x];
dfs_2(son[x],x);
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa&&edges[ee].to!=son[x]){
top[edges[ee].to]=edges[ee].to;
id[edges[ee].to]=++cnt;
id_[cnt]=edges[ee].to;
dfs_2(edges[ee].to,x);
}
} inline void push_up(int x){
tre[x].sum=tre[x<<].sum+tre[x<<|].sum;
} inline void push_down(int x){
tre[x<<].tag+=tre[x].tag;
tre[x<<].sum+=tre[x].tag*(tre[x<<].r-tre[x<<].l+);
tre[x<<|].tag+=tre[x].tag;
tre[x<<|].sum+=tre[x].tag*(tre[x<<|].r-tre[x<<|].l+);
tre[x].tag=;
return;
} void build(int x,int l,int r){
tre[x].l=l; tre[x].r=r;
if(l==r){
tre[x].sum=data[id_[l]];
return;
}
int mid=(l+r)>>;
build(x<<,l,mid);
build(x<<|,mid+,r);
push_up(x);
} void make(){
dfs_1(root,);
cnt=;
top[root]=root;
id[root]=cnt;
id_[cnt]=root;
dfs_2(root,);
build(,,n);
} void update(int x,int L,int R,ll c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].tag+=c;
tre[x].sum+=c*(tre[x].r-tre[x].l+);
return;
}
push_down(x);
int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) update(x<<,L,R,c);
else if(L>mid) update(x<<|,L,R,c);
else{
update(x<<,L,mid,c);
update(x<<|,mid+,R,c);
}
push_up(x);
} ll query_sum(int x,int L,int R){
if(L<=tre[x].l&&tre[x].r<=R)
return tre[x].sum;
push_down(x);
int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) return query_sum(x<<,L,R);
else if(L>mid) return query_sum(x<<|,L,R);
else return query_sum(x<<,L,mid)+query_sum(x<<|,mid+,R);
} void change(int u,int v,ll c){
int f1=top[u];
int f2=top[v];
while(f1!=f2){
// this ensure u and v is not at the same heavy chain
if(dep[f1] < dep[f2]){
// ensure that heavy chain 1 is under heavy chain 2
swap(f1,f2);
swap(u,v);
}
update(,id[f1],id[u],c);
u=fat[f1];
f1=top[u];
}
if(dep[u]>dep[v]) swap(u, v);
update(,id[u],id[v],c);
} ll find_sum(int u, int v)
{
ll sum=;
int f1=top[u];
int f2=top[v];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
sum+=query_sum(,id[f1],id[u]);
sum%=mod;
u=fat[f1];
f1=top[u];
}
if(dep[u]>dep[v]) swap(u, v);
sum+=query_sum(,id[u],id[v]);
return sum%mod;
} void solve(){
int opt,ss,tt;
ll c;
for(int i=;i<m;i++){
opt=read();
if(opt&){
//opt==3
if(opt&){
ss=read(); c=rea();
update(,id[ss],id[ss]+siz[ss]-,c);
}
//opt==1
else{
ss=read(); tt=read(); c=rea();
change(ss,tt,c);
}
}
else{
//opt==4
if(opt&){
ss=read();
printf("%lld\n",query_sum(,id[ss],id[ss]+siz[ss]-)%mod);
}
//opt==2
else{
ss=read(); tt=read();
printf("%lld\n",find_sum(ss,tt));
}
}
}
} int main(){
//freopen("data.in","r",stdin);
init();
make();
solve();
return ;
}

爱你锋利的伤痕  爱你成熟的天真

[luogu P3384] 【模板】树链剖分 [树链剖分]的更多相关文章

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

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

  2. 【模板】树链剖分(Luogu P3384)

    题目描述 众所周知 树链剖分是个好东西QWQ 也是一个代码量破百的算法 基本定义 树路径信息维护算法. ž将一棵树划分成若干条链,用数据结构去维护每条链,复杂度为O(logN). 其实本质是一些数据结 ...

  3. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

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

  4. 【Luogu】P3950部落冲突(树链剖分)

    题目链接 状态奇差无比,sbt都能错一遍. 不动笔光想没有想到怎么做,画图之后发现一个很明显的性质…… 那就是两个开战的部落,其中一个是另一个的父亲. 所以在儿子那里加个权值.查询的时候树链剖分查询链 ...

  5. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  6. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  7. BZOJ_3589_动态树_容斥原理+树链剖分

    BZOJ_3589_动态树_容斥原理+树链剖分 题意: 维护一棵树,支持1.子树内点权加上一个数  2.给出k条链,求路径上的点权和(重复的计算一次) (k<=5) 分析: 可以用树剖+线段树解 ...

  8. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  9. dsu+树链剖分+树分治

    dsu,对于无修改子树信息查询,并且操作支持undo的问题 暴力dfs,对于每个节点,对所有轻儿子dfs下去,然后再消除轻儿子的影响 dfs重儿子,然后dfs暴力恢复轻儿子们的影响,再把当前节点影响算 ...

  10. 2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)

    2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点 ...

随机推荐

  1. Java-集合框架总结

    集合框架: Java中的集合框架大类可分为Collection和Map:两者的区别: 1.Collection是单列集合:Map是双列集合 2.Collection中只有Set系列要求元素唯一:Map ...

  2. asp.net MVC 网站图片防盗链的几种方法

    目录 1. 通过 URL Rewrite Module 组件 2. 通过 nginx 图片防盗链 3.自定义 HttpHandler 处理 4. 通过 MVC 自定义路由规则防盗链 5. 通过 MVC ...

  3. unity3D:游戏分解之角色移动和相机跟随

          游戏中,我们经常会有这样的操作,点击场景中某个位置,角色自动移动到那个位置,同时角色一直是朝向那个位置移动的,而且相机也会一直跟着角色移动.有些游戏,鼠标滑动屏幕,相机就会围绕角色旋转. ...

  4. iOS工程师常用的命令行命令总结

    感觉有点标题党了. 作为一个iOS工程师,没有做过服务端,主要用的是mac电脑,此篇博文是记录我在工作,学习的过程中用的命令行命令的记录和归纳总结 一. mac命令行 1. cd /Users/xxx ...

  5. orcle :Could not initialize "D:\app\Administrator\product\11.2.0\dbhome_1\bin\oci.dll" Make sure you have the 32 bits Oracle Client installed.

    服务器重启后,数据库登录信息为空 错误信息: ---------------------------(Not logged on) - PL/SQL Developer---------------- ...

  6. nginx之 nginx-1.9.7 + tomcat-8.5.15 反向代理+应用负载均衡 安装配置

    环境说明:nginx 反向代理服务器 ip 为: 10.219.24.26tomcat1 应用服务器 ip 为: 10.219.24.21tomcat3 应用服务器 ip 为: 10.219.24.2 ...

  7. iOS-swift-协议和拓展

    1 协议(protocol) 使用关键字 protocol 创建协议. protocol ExampleProtocol { var simpleDescription: String { get } ...

  8. Java Web开发环境配置(JDK+Tomcat++IDEA 14)

    对于未接触过java web开发的大家而言,应该和我一样对java web编程开发比较迷茫,通过查一些资料,大致清楚了java web开发环境的一些基本配置,未做过相关编程的人员可以看一看,由于我刚接 ...

  9. shell中source与sh区别

    shell中使用source conf.sh,是直接运行conf.sh的命令,不创建子shell,类似与html中include,而sh是则创建子shell, 子shell里面 的变量父shell无法 ...

  10. Python Click 学习笔记(转)

    原文链接:Python Click 学习笔记 Click 是 Flask 的团队 pallets 开发的优秀开源项目,它为命令行工具的开发封装了大量方法,使开发者只需要专注于功能实现.恰好我最近在开发 ...