DFS序例题+感受

news/2024/11/20 1:29:24/文章来源:https://www.cnblogs.com/cjcf/p/18555953

最近在学dfs序的实际应用,专开个blog记录下感受
目前来看都是配合线段树,从树上问题变成区间问题

求和

https://ac.nowcoder.com/acm/problem/204871
题面:
已知有 \(n\) 个节点,有 \(n - 1\) 条边,形成一个树的结构。

给定一个根节点 \(k\),每个节点都有一个权值,节点 \(i\) 的权值为 \(v_i\)

\(m\) 个操作,操作有两种类型:

1 \(ax\):表示将节点 \(a\) 的权值加上 \(x\)

2 \(a\):表示求 \(a\) 节点的子树上所有节点的和(包括 \(a\) 节点本身
输入:
第一行给出三个正整数 \(n, m, k\),表示树的节点数、操作次数、和这棵树的根节点。

第二行给出 \(n\) 个正整数,第 \(i\) 个正整数表示第 \(i\) 个节点的权值 \(val_i\)

下面 \(n - 1\) 行每行两个正整数 \(u, v\),表示边的两个端点。

接下来 \(m\) 行,每行给出一个操作。
输出:
对于每个类型为 2 的操作,输出一行一个正整数,表示以a为根的子树的所有节点的权值和
数据范围:
\( \begin{align*} 1 &\leq n, m \leq 1e6, 1 \leq k \leq n \\ 1 &\leq u, v \leq n \\ 1 &\leq a \leq n \\ -1e6 &\leq val_i, x \leq 1e6 \end{align*} \)
样例:
5 6 1
1 2 3 4 5
1 3
1 2
2 4
2 5
1 2 10
1 3 10
1 4 5
1 5 1
2 3
2 2
————————
13
27
感受:算是个很基本的入门题了,就是dfs序+线段树,直接一遍过了

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                   long long 
#define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
void fio()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
}
struct s
{ll v,l,r;ll lazy;
}p[1000002<<2];
void build(ll i,ll l,ll r)
{p[i].v=0;p[i].l=l,p[i].r=r;if(l==r)return ;build(i<<1,l,(l+r)>>1);build(i<<1|1,(l+r>>1)+1,r);
}
void update(ll i,ll l,ll r,ll v)
{if(l==p[i].l&&r==p[i].r){p[i].v+=v;return ;}ll mid=(p[i].l+p[i].r)>>1;if(l<=mid)update(i<<1,l,min(mid,r),v);if(r>=mid+1)update(i<<1|1,max(mid+1,l),r,v);p[i].v=p[i<<1].v+p[i<<1|1].v;
}
ll query(ll i,ll l,ll r)
{ll ans=0;if(l==p[i].l&&r==p[i].r){ans+=p[i].v;return ans;}ll mid=(p[i].l+p[i].r)>>1;if(l<=mid)ans+=query(i<<1,l,min(mid,r));if(r>=mid+1)ans+=query(i<<1|1,max(mid+1,l),r);return ans;
}
ll a[1000002];
ll ne[2000002];
ll to[2000002];
ll h[2000002];
ll b[2000002];
ll cnt=0;
ll gs=0;
void add(ll l,ll r)
{to[cnt]=r;ne[cnt]=h[l];h[l]=cnt++;	
}
void dfs(ll k,ll fa)
{gs++;b[gs]=k;for(ll i=h[k];i>=0;i=ne[i]){if(to[i]==fa)continue;dfs(to[i],k);}gs++;b[gs]=k;
}
ll vis[2000002];
pair<ll,ll>ans[1000002];
int main()
{fio();
ll n,m,k;
cin>>n>>m>>k;
for(ll i=1;i<=n;i++)cin>>a[i];
memset(h,-1,sizeof h);
build(1,1,n);
for(ll i=1;i<=n-1;i++)
{
ll l,r;
cin>>l>>r;
add(l,r);
add(r,l);
}
dfs(k,0);
cnt=0;
ll last=0;
for(ll i=1;i<=gs;i++)
{
if(vis[b[i]]==0)
{cnt++;
update(1,cnt,cnt,a[b[i]]);vis[b[i]]=cnt;last=cnt;
}
else 
{
ans[b[i]]={vis[b[i]],last};
}
}
//cout<<query(1,1,5)<<endl;
while(m--)
{ll op;cin>>op;switch(op){case 1:{ll x,y;cin>>x>>y;update(1,vis[x],vis[x],y);break;}case 2:{ll x;cin>>x;cout<<query(1,ans[x].first,ans[x].second)<<endl;break;}}
}
}

华华和月月种树

https://ac.nowcoder.com/acm/problem/23051
题面:
华华看书了解到,一起玩养成类的游戏有助于两人培养感情。所以他决定和月月一起种一棵树。因为华华现在也是信息学高手了,所以他们种的树是信息学意义下的。

华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有0号节点,权值为0。接下来有两种操作:

操作1: 输入格式 \(1i\),表示月月氪金使节点 \(i\) 长出了一个新的儿子节点,权值为0,编号为当前最大编号+1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。

操作2: 输入格式 \(2ia\),表示华华上线做任务使节点 \(i\) 的子树中所有节点(即它和它的所有子孙节点)权值加 \(a\)

但是月月有时会检查华华有没有认真维护这棵树,会作出询问:

询问3: 输入格式 \(3i\),华华需要给出 \(i\) 节点此时的权值。

华华当然有认真种树了,不过还是希望能写个程序以备不时之需。
输入:
第一行一个正整数 \(M\),接下来 \(M\) 行,每行先输入一个正整数 \(O\) 表示操作类型,再输入一个非负整数 \(i\) 表示操作或询问的节点编号,如果 \(O=2\),再输入一个正整数 \(a\)
输出:
对于每个询问 \(3\),输出一个非负整数表示询问的答案。
样例:
9
1 0
2 0 1
3 0
3 1
1 0
1 1
2 0 2
3 1
3 3
——————
1
1
3
2
数据范围:
\(1 \leq M \leq 4 \times 10^5\),保证操作1的数量不超过 \(10^5\),保证操作2中的参数 \(a\) 满足 \(1 \leq a \leq 999\)
感受:感觉不难,但是错了快15次吧,为什么呢?一是手敲线段树,区间修改漏了每次都是修改区间值,二是认为可以二分要修改的范围,这里不是子树嵌套子树,所以二分不行。三是每次遇到新节点时,得减少值,这里直接问了区间和,然后区间里每个数减去区间和了。被自己逗笑了

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                   long long 
#define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
const ll maxn = 4e5 + 5;
void fio()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
}
struct s
{ll v, l, r;ll lazy;
}p[maxn << 2];
void build(ll i, ll l, ll r)
{p[i].v = 0;p[i].l = l, p[i].r = r;p[i].lazy = 0;if (l == r)return;build(i << 1, l, (l + r) >> 1);build(i << 1 | 1, (l + r >> 1) + 1, r);
}
void push_down(ll i)
{if (p[i].lazy){p[i << 1].v += (p[i << 1].r - p[i << 1].l + 1) * p[i].lazy;p[i << 1 | 1].v += (p[i << 1 | 1].r - p[i << 1 | 1].l + 1) * p[i].lazy;p[i << 1 | 1].lazy += p[i].lazy;p[i << 1].lazy += p[i].lazy;p[i].lazy = 0;}
}
void update(ll i, ll l, ll r, ll v)
{if (l == p[i].l && r == p[i].r){p[i].v += (r-l+1)*v;p[i].lazy += v;return;}push_down(i);ll mid = (p[i].l + p[i].r) >> 1;if (l <= mid)update(i << 1, l, min(mid, r), v);if (r >= mid + 1)update(i << 1 | 1, max(mid + 1, l), r, v);p[i].v = p[i << 1].v + p[i << 1 | 1].v;
}
ll query(ll i, ll l, ll r)
{ll ans = 0;if (l == p[i].l && r == p[i].r){ans += p[i].v;return ans;}push_down(i);ll mid = (p[i].l + p[i].r) >> 1;if (l <= mid)ans += query(i << 1, l, min(mid, r));if (r >= mid + 1)ans += query(i << 1 | 1, max(mid + 1, l), r);return ans;
}
vector<ll>g[500000];
ll a[maxn];
ll b[maxn << 1];
ll cnt = 0;
ll gs = 0;
void dfs(ll k, ll fa)
{gs++;b[gs] = k;for (auto j : g[k]){dfs(j, k);}gs++;b[gs] = k;
}
ll vis[maxn];
ll vi[maxn];
ll d[maxn];
pair<ll, ll>ans[maxn];
struct u
{ll x;ll l, r;
}f[maxn];
int main()
{fio();ll n;cin >> n;build(1, 1, n);ll o = 1;ll cs = 0;for (ll i = 1; i <= n; i++){cin >> f[i].x;if (f[i].x == 2)cin >> f[i].l >> f[i].r;else{cin >> f[i].l;if (f[i].x == 1){f[i].r=o;g[f[i].l].push_back(o);	o++;}}}dfs(0, -1);cnt = 0;for (ll i = 1; i <= gs; i++){if (vis[b[i]] == 0){cnt++;vis[b[i]] = cnt;d[cnt] = vi[b[i]];}else{ans[b[i]] = { vis[b[i]],cnt };}}cnt = 0;ll fs=0;for (ll i = 1; i <= n; i++){if (f[i].x == 1){ll u=query(1,ans[f[i].r].first,ans[f[i].r].first);update(1, ans[f[i].r].first, ans[f[i].r].first, -u);}else if (f[i].x == 2){update(1, ans[f[i].l].first, ans[f[i].l].second, f[i].r);}else if (f[i].x == 3){cout << query(1, ans[f[i].l].first, ans[f[i].l].first) << endl;}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837101.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 学习笔记(一)-Redis 安装

一、Redis简介 (1)什么是Redis ​ Redis 是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。在企业开发中, 主要用于做数据库、缓…

交互式备忘单: 汇集了各种有用的安全工具

这份工具包是一个交互式备忘单,汇集了各种有用的安全工具,主要用于渗透测试或红队练习。这些工具来自于Github仓库和其他公开来源。以下是工具列表及其分类: AD:用于Active Directory安全的工具。 BinaryExp:用于二进制漏洞利用/入侵的工具。 Blue:用于蓝队操作和防御的工…

29. 使用MySQL之数据库维护

1. 备份数据 像所有数据一样,MySQL的数据也必须经常备份。由于MySQL数据库是基于磁盘的文件,普通的备份系统和例程就能备份MySQL的数据。但是,由于这些文件总是处于打开和使用状态,普通的文件副本备份不一定总是有效。 下面列出这个问题的可能解决方案。使用命令行实用程序…

QT实现组合键监测

QT实现快捷键监测,完成某些组合键功能参考于:Qt 获取组合键 键盘按住某键 鼠标组合实现 - Andy5020 - 博客园MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);QWidget::installEventFilter(this); }bool MainW…

GitLab快速上手指南上篇

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.gitlab的基本配置1 登录gitlab并配置汉化2 修改管理员密码3 修改头像4 关闭账号注册功能5 修改邮箱地址二.gitlab用户,组,项目管理1.用户,组,项目查看2.用户管理2.1 新建用户2.2 用户创建成功2.3 …

【springboot开发】Spring Boot3.3 内部配置与外部配置的差异及其应用

在 Spring Boot 开发中,配置管理是关键的组成部分。配置不仅影响应用程序的行为,还直接关系到应用的灵活性和可维护性。Spring Boot 提供了多种方式来管理配置,其中包括内部配置和外部配置。这两种配置方式各有其优势和应用场景,了解它们的特点和使用场景有助于在开发过程中…

DCL

创建用户通过create user 来创建用户 create user 用户名;(不带密码) create user 用户名 identified by 密码;登录用户发现他可以访问的表少,权限比较少; exit 可以退出登录 用户授权 用grant all|权限1,权限2..on 数据库.表 to 用户(with grant option)【加了括号中命…

【springboot开发】Spring Boot 配置文件高级用法

一、总体优先级顺序二、应用配置文件的详细优先级三、文件类型优先级四、特定环境配置五、配置文件高级用法六、案例: 多配置文件处理方式Spring Boot配置文件的优先级是一个重要的概念,它决定了当存在多个配置文件时,哪个配置文件中的配置将被优先采用。 一、总体优先级顺序…

【微服务】微服务中token鉴权设计的4种方式总结

一、JWT鉴权1.1 概述1.2 实现步骤1.2.1 用户登录1.2.2 存储JWT 1.2.3 请求携带JWT1.2.4 服务端验证JWT 1.3 优点 二、OAuth 2.0鉴权2.1 概述2.2 实现步骤2.2.1 授权服务器2.2.2 资源服务器 2.2.3 客户端 2.3 优点三、统一授权中心(API Gateway)3.1 概述3.2 实现步骤 3.2.1 部…

【架构】一文搞懂多规格商品、组合商品模型设计

今天聊聊多规格商品、组合商品模型设计。 一、多规格商品 1.1 什么是多规格商品 多规格商品是指同一款商品具有多个不同的规格或属性,例如颜色、尺寸、材质、容量等。这些规格使得商品能够满足不同消费者的偏好和需求。在新零售系统中,多规格商品通常会以一个商品条目展示,消…

【架构】多租户系统的核心概念模型

让我们深入探讨一下多租户系统的概念模型。概念模型是多租户系统的"骨架",帮助我们理解系统各部分的组织和运作方式。 多租户的核心概念模型 • 租户:通常指一个企业客户,不同租户之间的数据和行为是相互隔离的。• 用户:某个租户内的具体使用者,使用账号、密码…

WinForm 设计器中DPI感知错误解决方法

这张图是WinForm在1080P分辨率下开发的一个Form,但是代码到高分辨率屏幕就会变成这个鸟样虽然说可以通过DPI感知让程序在运行的时候显示出正确的样式,但是这样让我们在设计的时候很是苦恼 在翻看了WinForm微软官方在Net8的更新,发现了这样的一条:我们在项目csproj里面加入一…