树链剖分-模板题 HAOI2015

  1 #include <stdio.h>
  2 #include <vector>
  3
  4 using namespace std;
  5
  6 typedef long long LL;
  7
  8 const int _N = 1000000;
  9
 10 vector<LL> G[_N];
 11 LL Size[_N], ID[_N], Anc[_N], Hson[_N], D[_N], Dad[_N], A[_N];
 12 LL Seg_root, Seg_cnt, L[_N], R[_N], Sum[_N], Lazy[_N];//segt
 13 LL N, ID_cnt;
 14
 15 void Find(LL node, LL dad, LL deep)
 16 {
 17     LL mx = -1;
 18     Size[node] = 1, D[node] = deep, Dad[node] = dad;
 19     for (LL i = 0; i != G[node].size(); ++i) {
 20         LL v = G[node][i];
 21         if (v == dad) continue;
 22         Find(v, node, deep + 1), Size[node] += Size[v];
 23         if (mx == -1 || Size[G[node][mx]] < Size[v]) mx = i;
 24     }
 25     if (mx != -1) Hson[node] = G[node][mx];
 26     return;
 27 }
 28
 29 void Connect(LL node, LL anc)
 30 {
 31     ID[node] = ++ID_cnt, Anc[node] = anc;
 32     if (Hson[node]) Connect(Hson[node], anc);
 33     for (LL i = 0; i != G[node].size(); ++i) {
 34         LL v = G[node][i];
 35         if (v == Dad[node] || v == Hson[node]) continue;
 36         Connect(v, v);
 37     }
 38     return;
 39 }
 40
 41 void Seg_PD(LL &p, LL l, LL r)
 42 {
 43     if (l == r) { Lazy[p] = 0; return; }
 44
 45     if (!L[p]) L[p] = ++Seg_cnt;
 46     if (!R[p]) R[p] = ++Seg_cnt;
 47     LL mid = l+r >> 1;
 48     Sum[L[p]] += Lazy[p] * (mid-l+1), Lazy[L[p]] += Lazy[p];
 49     Sum[R[p]] += Lazy[p] * (r-mid), Lazy[R[p]] += Lazy[p];
 50     Lazy[p] = 0;
 51     return;
 52 }
 53
 54 void Seg_Add(LL &p, LL l, LL r, LL s, LL t, LL d)
 55 {
 56     if (!p) p = ++Seg_cnt;
 57     if (s <= l && r <= t) { Sum[p] += d * (r-l+1), Lazy[p] += d; return; }
 58     LL mid = l+r >> 1;
 59     if (Lazy[p]) Seg_PD(p, l, r);
 60     if (s <= r && t > mid) Seg_Add(R[p], mid+1, r, s, t, d);
 61     if (s <= mid && t >= l) Seg_Add(L[p], l, mid, s, t, d);
 62     Sum[p] = Sum[R[p]] + Sum[L[p]];
 63     return;
 64 }
 65
 66 LL Seg_Qry(LL &p, LL l, LL r, LL s, LL t)
 67 {
 68     if (!p) p = ++Seg_cnt;
 69     if (s <= l && r <= t) return Sum[p];
 70     LL mid = l+r >> 1, sum = 0;
 71     if (Lazy[p]) Seg_PD(p, l, r);
 72     if (s <= r && t > mid) sum += Seg_Qry(R[p], mid+1, r, s, t);
 73     if (s <= mid && t >= l) sum += Seg_Qry(L[p], l, mid, s, t);
 74     return sum;
 75 }
 76
 77 void Add_s(LL k, LL d)
 78 {
 79     Seg_Add(Seg_root, 1, N, ID[k], ID[k], d);
 80     return;
 81 }
 82
 83 void Add_r(LL k, LL d)
 84 {
 85     Seg_Add(Seg_root, 1, N, ID[k], ID[k] + Size[k] - 1, d);
 86     return;
 87 }
 88
 89 LL Qry(LL x, LL y)
 90 {
 91     LL sum = 0;
 92     while (Anc[x] != Anc[y]) {
 93         if (D[Anc[x]] < D[Anc[y]]) swap(x, y);
 94         sum += Seg_Qry(Seg_root, 1, N, ID[Anc[x]], ID[x]);
 95         x = Dad[Anc[x]];
 96     }
 97     if (D[x] > D[y]) swap(x, y);
 98     sum += Seg_Qry(Seg_root, 1, N, ID[x], ID[y]);
 99     return sum;
100 }
101
102 int main_main()
103 {
104     LL M, i;
105     scanf("%lld%lld", &N, &M);
106     for (i = 1; i <= N; ++i) scanf("%lld", &A[i]);
107     for (i = 1; i < N; ++i) {
108         LL t1, t2;
109         scanf("%lld%lld", &t1, &t2);
110         G[t1].push_back(t2), G[t2].push_back(t1);
111     }
112
113     Find(1, -1218, 1);
114     Connect(1, 1);
115     for (i = 1; i <= N; ++i) Add_s(i, A[i]);
116
117     for (i = 1; i <= M; ++i) {
118         LL ins, t1, t2;
119         scanf("%lld%lld", &ins, &t1);
120         if (ins == 1) {//add_s
121             scanf("%lld", &t2);
122             Add_s(t1, t2);
123         } else if (ins == 2) {//add_r
124             scanf("%lld", &t2);
125             Add_r(t1, t2);
126         } else if (ins == 3) {//qry
127             printf("%lld\n", Qry(1, t1));
128         }
129     }
130     return 0;
131 }
132
133 const int main_stack=16;
134 char my_stack[128<<20];
135 int main() {
136   __asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory");
137   __asm__("movl %%eax, %%esp;\n"::"a"(my_stack+sizeof(my_stack)-main_stack):"%esp");
138   main_main();
139   __asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp");
140   return 0; //add stack copy copy!!!
141 } 

敲了一个树剖模板,顺便复习了一下动态开点的线段树.

NKOJ需要扩栈!

题目

【HAOI2015】树上操作
时间限制 : - MS   空间限制 : 265536 KB 
评测说明 : 1s
问题描述

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

操作 1 :把某个节点 x 的点权增加 a 。

操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。

操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

输入格式

第一行包含两个整数 N, M 。表示点数和操作数。

接下来一行 N 个整数,表示树中节点的初始权值。

接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。

再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操

作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

输出格式

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

样例输入

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

样例输出

6
9
13

提示

对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

原文地址:https://www.cnblogs.com/ghcred/p/8877031.html

时间: 2024-08-30 00:38:44

树链剖分-模板题 HAOI2015的相关文章

HDU 3966 Aragorn&#39;s Story(树链剖分 模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, th

BZOJ 2243 染色 | 树链剖分模板题进阶版

BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上还是原树上,把两个区间的信息合并的时候,要注意中间相邻两个颜色是否相同. 这代码好长啊啊啊啊 幸好一次过了不然我估计永远也De不出来 #include <cstdio> #include <cstring> #include <algorithm> using namesp

bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1行,每行

spoj Query on a tree(树链剖分模板题)

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

SPOJ QTREE Query on a Tree【树链剖分模板题】

树链剖分,线段树维护~ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int MAXN = 10014; struct Edge { int to,next; }edge[MAXN*2]; int head[MAXN],tot; int top[MA

BZOJ 1036 树链剖分模板题

BZOJ 1036 题意:一棵树,每个点有权值,三种操作:修改一个点的值:询问一条链上最大值:询问一条链上权值和. tags:模板题 // bzoj 1036 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (int i=a;i<=b;i++) #define F(i,b,a)

【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题

sth神犇的模板: //bzoj1036 题目:一个n个点的树每个点有一个权值,支持修改单点权值,求某两点路径上的点权和或最大点权. #include <cstdio> using namespace std; int pos[30001],f[30001],up[30001],son[30001],size[30001],a[80001],next[80001],last[30001],sum[100001],max[100001];//pos是指某点在线段树中的位置:f是父节点:up是所在

BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I