[luogu 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取模)

输入输出样例

输入样例#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 \leq 10, M \leq 10N≤10,M≤10

对于70%的数据: N \leq {10}^3, M \leq {10}^3N≤10​3​​,M≤10​3​​

对于100%的数据: N \leq {10}^5, M \leq {10}^5N≤10​5​​,M≤10​5​​

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

样例说明:

树的结构如下:

各个操作如下:

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

树剖模板题啊。。。都快不会打树剖了。

显然,对于这种题目,就要将每一个点根据dfs序映射到线性表上,然后用线段树等维护。

对于1,2操作,就是树剖的基本修改-查询操作;

对于3,4操作,也就是在x的子树里修改查询。那么,一个子树内部的点在dfs序对应的线性表上是连续的,也就可以通过线段树维护了。

ps:树剖都是码农题。。不过打得倒还挺爽。

code:

 %:pragma GCC optimize()
 #include<bits/stdc++.h>
 #define mid (((l)+(r))>>1)
 #define amod(x,y) (((x)+=(y))%=T)
 #define LL long long
 #define IL inline
 using namespace std;
 ;
 ],son[N<<];
 int dep[N],fa[N],si[N],down[N],top[N],bel[N],idl[N],idr[N];
 LL v[N],v0[N],a[N<<],t[N<<],T;
 IL LL read() {
     LL x=; char ch=getchar();
     ') ch=getchar();
     +ch-',ch=getchar();
     return x;
 }
 IL void add(int x,int y) {nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y;}
 IL void dfs(int x,int p) {
     dep[x]=dep[p]+,fa[x]=p,si[x]=,down[x]=n+;
     for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=p) {
         dfs(son[j],x),si[x]+=si[son[j]];
         down[x]=(si[down[x]]<si[son[j]])?son[j]:down[x];
     }
 }
 IL void pre(int x,int p) {
     idl[x]=++cloc;
     ) top[down[x]]=top[x],bel[down[x]]=bel[x],pre(down[x],x);
     for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=p&&son[j]!=down[x]) {
         top[son[j]]=son[j],bel[son[j]]=++chain,pre(son[j],x);
     }
     idr[x]=cloc;
 }
 IL LL am(LL x,LL y) {return (x+y)%T;}
 IL ],a[c<<|]);}
 IL void pushD(int c,int l,int r) {
     amod(t[c<<],t[c]);
     amod(t[c<<|],t[c]);
     amod(a[c<<],t[c]*(LL)(mid-l+));
     amod(a[c<<|],t[c]*(LL)(r-mid));
     t[c]=;
 }
 IL void B(int c,int l,int r) {
     if (l==r) {a[c]=v0[l]%T; return;}
     B(c<<,l,mid),B(c<<|,mid+,r);
     pushU(c);
 }
 IL void U(int c,int l,int r,LL v,int liml,int limr) {
     )),pushD(c,l,r); return;}
     pushD(c,l,r);
     ,l,mid,v,liml,limr);
     |,mid+,r,v,liml,limr);
     ,l,mid,v,liml,mid),U(c<<|,mid+,r,v,mid+,limr);
     pushU(c);
 }
 IL LL A(int c,int l,int r,int liml,int limr) {
     if (l>=liml&&r<=limr) return a[c]%T;
     pushD(c,l,r); LL ret=;
     ,l,mid,liml,limr));
     |,mid+,r,liml,limr));
     ,l,mid,liml,mid)),amod(ret,A(c<<|,mid+,r,mid+,limr));
     pushU(c); return ret%T;
 }
 IL void chain_U(int x,int y,LL v) {
     while (bel[x]!=bel[y]) {
         ,,n,v,idl[top[x]],idl[x]),x=fa[top[x]];
         ,,n,v,idl[top[y]],idl[y]),y=fa[top[y]];
     }
     if (dep[x]>dep[y]) swap(x,y);
     U(,,n,v,idl[x],idl[y]);
 }
 IL LL chain_A(int x,int y) {
     LL ret=;
     while (bel[x]!=bel[y]) {
         ,,n,idl[top[x]],idl[x])),x=fa[top[x]];
         ,,n,idl[top[y]],idl[y])),y=fa[top[y]];
     }
     if (dep[x]>dep[y]) swap(x,y);
     amod(ret,A(,,n,idl[x],idl[y]));
     return ret%T;
 }
 IL ,,n,v,idl[x],idr[x]);}
 IL LL tree_A(,,n,idl[x],idr[x])%T;}
 int main() {
     n=read(),m=read(),r=read(),T=read();
     ; i<=n; i++) v[i]=read();
     ,x,y; i<n; i++) x=read(),y=read(),add(x,y),add(y,x);
     dep[]=,si[n+]=,dfs(r,),pre(r,);
     ; i<=n; i++) v0[idl[i]]=v[i];
     B(,,n);
     for (int o,x,y,z; m; m--) {
         o=read(),x=read(),y=(o<)?read():,z=(o&)?read():;
         switch (o) {
             :chain_U(x,y,(LL)z%T); break;
             :printf("%lld\n",chain_A(x,y)%T); break;
             :tree_U(x,(LL)z%T); break;
             :printf("%lld\n",tree_A(x)%T); break;
         }
     }
     ;
 }

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

  1. 【Luogu P3384】树链剖分模板

    树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...

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

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

  3. P3384 [模板] 树链剖分

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

  4. luoguP3384 [模板]树链剖分

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

  5. 模板 树链剖分BFS版本

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

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

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

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

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

  8. [note]树链剖分

    树链剖分https://www.luogu.org/problemnew/show/P3384 概念 树链剖分,是一种将树剖分成多条不相交的链的算法,并通过其他的数据结构来维护这些链上的信息. 最简单 ...

  9. Luogu P3384 【【模板】树链剖分】

    转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...

随机推荐

  1. latex建立参考文献的超链接

    在Latex生成的pdf文档中建立超链接(如从正文到参考文献,从目录到相应内容,从页码编号到实际页面等),有利于读者快速定位当前阅读的信息. 如何在生成的pdf文件中包含超链接呢?需要注意一下两点: ...

  2. 理解 Redis(3) - 字符串值

    正如前面所讲的, redis 的数据结构就是一系列的键值对键 -> printable ASCII (可打印的 ASCII 码, 最大值是 512MB)值 -> Primitives (基 ...

  3. 【BZOJ】3295: [Cqoi2011]动态逆序对

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3295 mamaya,弱鸡xrdog终于会写树套树啦.... 将树状数组中每一个节点看成一棵 ...

  4. CAP原则

    CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三者不可兼得 分布式系 ...

  5. dll多个版本问题

    在配置文件设置不同版本的dll即可 配置文件如下 configuration 节点下面的  runtime 节点新增各个版本配置内容 <runtime> <assemblyBindi ...

  6. VC.时间_ZC测试代码

    1. #include <windows.h> #include <stdio.h> void TimeNowZ( char* _pc ) { SYSTEMTIME sys; ...

  7. 《剑指offer》第六十八题(树中两个结点的最低公共祖先)

    // 面试题68:树中两个结点的最低公共祖先 // 题目:输入两个树结点,求它们的最低公共祖先. #include <iostream> #include "Tree.h&quo ...

  8. Codeforces 801B - Valued Keys

    B. Valued Keys 题目链接:http://codeforces.com/contest/801/problem/B time limit per test 2 seconds memory ...

  9. iframe和ajax文件上传方法

    为什么使用这两种方法文件上传呢,主要是因为局部刷新问题 上传问题,主要是使用form表单,或者用请求一个文件上传 iframe 大多网站都是有一个整体的固定结构,然后进行局部刷新,我们可以使用AJAX ...

  10. 取代iframe框架

    一.frameset1. 属性①border设置框架的边框粗细.②bordercolor设置框架的边框颜色.③frameborder设置是否显示框架边框.设定值只有0.1:0 表示不要边框,1 表示要 ...