DFS序--树状数组
这里先说下有关大法师(DFS序)的内容....
子树修改----求子树和
-
虽然就是一个简() 单 ( ) 的 区间修改,加上区间查询
-
有人就会“密西”道:这不线段树嘛,有手就行。
-
也许还会有人会曰:线段树他不香吗?
But...
-
我用的树状数组 (/滑稽/)
因此 我来交代一下我的做法
树状数组学好了吗,看看这吧,guy!
请看Code
-
方便读者进行修改,加以理解的代码
```cpp
/*
DFSN: 子树修改,子树查询。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
const int manx = 1e5 + 10;
const int mod = 1234567890;
const int minx = 1e7 + 10;
struct node{
int u;
int v;
int nxt;
int w;
}e[manx<<1];
int cur,sum[manx],summ[manx],head[manx],deep[manx],js,l[manx],r[manx],cnt,n,m,dfn[manx];
int add(int u,int v){
e[++cnt].u = u;
e[cnt].nxt = head[u];
e[cnt].v = v;
//e[cnt].w = w;
head[u] = cnt;
}
inline void init(){
cnt=js=0;
clr(head,-1);clr(sum,0);
cur=n<<1;
}
void dfs(int u, int pre){
//cout<<1<<endl;
l[u] = ++js;
dfn[js] = u;
for(int i = head[u];~i;i = e[i].nxt){
int v = e[i].v;
if( v == pre ) continue;
dfs(v,u);
}
r[u] = ++js;
dfn[js] = u;
}
struct Binary_tree{
long long tr[manx];
void add(int i,long long x)
{
//cout<<i<<" "<<x<<endl;
while(i<=n*2)
{
tr[i]+=x;
i+=i&-i;
}
}
long long qsum(int i)
{
long long ret=0;
while(i>0)
{
ret+=tr[i];
i-=i&-i;
}
return ret;
}
}A,B;
int main(){
cin>>n>>m;
init();
for(int i = 1; i <= n - 1;i ++){
int x;int y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,1);
for(int i = 1;i <= m; i++){
int x;int y;int z;
cin>>x>>y;
if(x == 1){
cin>>z;
A.add(l[y],z);
A.add(r[y]+1,-z);
B.add(l[y],z*(l[y]-1));
B.add(r[y]+1,-z*r[y]);
// cout<<A.tr [l[y]]<<" "<<A.tr [r[y]+1]<<endl;
// for(int j = 1;j <= n *2;j ++)
// cout<<A.tr[j]<<" ";
// cout<<endl;
// for(int j = 1;j <= n *2;j ++)
// cout<<B.tr[j]<<" ";
// cout<<endl;
}
else
{
// for(int j = 1;j <= n*2;j++)
// cout<<j<<" "<<A.qsum(j)<<" "<<endl;
// for(int j = 1;j <= n*2;j++)
// cout<<j<<" "<<B.qsum(j)<<" "<<endl;
// for(int j = 1; j <= n;j++)
// cout<<j<<" "<<l[j]<<" "<<r[j]<<endl;
cout<<(A.qsum(r[y])*r[y]-(l[y]-1)*A.qsum(l[y]-1))-B.qsum(r[y])+B.qsum(l[y]-1);
}
}
}
-
简洁的Code
/*
DFSN: 子树修改,子树查询。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
const int manx = 1e5 + 10;
const int mod = 1234567890;
const int minx = 1e7 + 10;
struct node{
int u;
int v;
int nxt;
int w;
}e[manx<<1];
int cur,sum[manx],summ[manx],head[manx],deep[manx],js,l[manx],r[manx],cnt,n,m,dfn[manx];
int add(int u,int v){
e[++cnt].u = u;
e[cnt].nxt = head[u];
e[cnt].v = v;
//e[cnt].w = w;
head[u] = cnt;
}
inline void init(){
cnt=js=0;
clr(head,-1);clr(sum,0);
cur=n<<1;
}
void dfs(int u, int pre){
l[u] = ++js;
dfn[js] = u;
for(int i = head[u];~i;i = e[i].nxt){
int v = e[i].v;
if( v == pre ) continue;
dfs(v,u);
}
r[u] = ++js;
dfn[js] = u;
}
struct Binary_tree{
long long tr[manx];
void add(int i,long long x)
{
while(i<=n*2)
{
tr[i]+=x;
i+=i&-i;
}
}
long long qsum(int i)
{
long long ret=0;
while(i>0)
{
ret+=tr[i];
i-=i&-i;
}
return ret;
}
}A,B;
int main(){
cin>>n>>m;
init();
for(int i = 1; i <= n - 1;i ++){
int x;int y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,1);
for(int i = 1;i <= m; i++){
int x;int y;int z;
cin>>x>>y;
if(x == 1){
cin>>z;
A.add(l[y],z);
A.add(r[y]+1,-z);
B.add(l[y],z*(l[y]-1));
B.add(r[y]+1,-z*r[y]);
}
else
{
cout<<(A.qsum(r[y])*r[y]-(l[y]-1)*A.qsum(l[y]-1))-B.qsum(r[y])+B.qsum(l[y]-1);
}
}
}
这里给个特别需要注意的地方
(因为我在这卡了一天)
void add(int i,long long x)
{
while(i<=n*2)
{
tr[i]+=x;
i+=i&-i;
}
}
中的 的范围应该是 !!!
原因不想解释,可能因为我太菜了吧~~~
我想再填一句
其实树状数组局限性很大,比如这个题,
颜色修改不容易实现
本文作者:zxsoul
本文链接:https://www.cnblogs.com/zxsoul/p/13916864.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步