华华和月月种树-题解

华华和月月种树

https://ac.nowcoder.com/acm/problem/23051

*题目描述 *
华华看书了解到,一起玩养成类的游戏有助于两人培养感情。所以他决定和月月一起种一棵树。因为华华现在也是信息学高手了,所以他们种的树是信息学意义下的。
华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有 0 号节点,权值为 0 。接下来有两种操作:
操作 1:输入格式,表示月月氪金使节点 i 长出了一个新的儿子节点,权值为0,编号为当前最大编号 +1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。
操作 2:输入格式 ,表示华华上线做任务使节点 i 的子树中所有节点(即它和它的所有子孙节点)权值加 a 。
但是月月有时会检查华华有没有认真维护这棵树,会作出询问:
询问 3:输入格式,华华需要给出 i 节点此时的权值。
华华当然有认真种树了,不过还是希望能写个程序以备不时之需。

输入描述:
第一行一个正整数M,接下来M行,每行先输入一个正整数O表示操作类型,再输入一个非负整数i表示操作或询问的节点编号,如果O=2,再输入一个正整数a。

思路:首先这是一棵树,我们采用离线的做法先将这颗树建好,然后跑一遍dfs序,记录子树大小。针对操作1我们只需要将该点的权值设置为0就行,至于为啥不用修改子孙节点,这是因为子孙节点一定是在当前节点之后才长出的,所以我们只需在下一次操作1修改就行。针对操作2,我们就需要更新该节点以及他的子孙节点了。剩下的操作3就是查询操作了。这里涉及到单点修改,区间修改,单点查询,经典线段树嘛。

代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[400005],lazy[400005],siz[400005],vis[400005];
int sum[400005],id=0;
vector<int>edge[400005];
struct Node{
    int op,pos,w;
}b[400005];
int dfs(int u)//跑出dfs序用来跑线段树
{
    vis[u]=++id;//记录该节点的访问时间即时间戳
    for(int i=0;i<edge[u].size();i++){
        int v=edge[u][i];
        siz[u]+=dfs(v);
    }
    return siz[u]+1;//子树大小不包括自己,方便在dfs序中更新子孙节点
}
void pushdown(int p)//线段树向下更新
{
    if(lazy[p]){
        lazy[p*2]+=lazy[p];
        lazy[p*2+1]+=lazy[p];
        sum[p*2]+=lazy[p];
        sum[p*2+1]+=lazy[p];
        lazy[p]=0;
    }
}
void updateone(int p,int l,int r,int pos)//单点修改
{
    if(l==r){
        sum[p]=0;
        return;
    }
    pushdown(p);
    int mid=(l+r)/2;
    if(pos<=mid)updateone(p*2,l,mid,pos);
    else updateone(p*2+1,mid+1,r,pos);
}
void updatemul(int p,int l,int r,int ul,int ur,int w)//区间修改
{
    if(ul<=l&&ur>=r){
        sum[p]+=w;
        lazy[p]+=w;

        return ;
    }
    pushdown(p);
    int mid=(l+r)/2;
    if(ul<=mid)updatemul(p*2,l,mid,ul,ur,w);
    if(ur>mid)updatemul(p*2+1,mid+1,r,ul,ur,w);
}
int query(int p,int l,int r,int pos)//单点查询
{
    if(l==r){
        return sum[p];
    }
    pushdown(p);
    //printf("%d %d %d\n",l,r,sum[p]);
    int mid=(l+r)/2;
    if(pos<=mid)return query(p*2,l,mid,pos);
    else return query(p*2+1,mid+1,r,pos);
}
int main()
{
    int M;
    scanf("%d",&M);
    int n=0;
    for(int i=0;i<M;i++){
        int op,pos,w;
        scanf("%d",&op);
        b[i].op=op;
        if(op==1){
            scanf("%d",&pos);
            b[i].pos=pos;
            n++;
            edge[pos].push_back(n);
        }else if(op==2){
            scanf("%d%d",&pos,&w);
            b[i].pos=pos,b[i].w=w;
        }else{
            scanf("%d",&pos);
            b[i].pos=pos;
        }
    }
    dfs(0);
    n=0;
    for(int i=0;i<M;i++){
        if(b[i].op==1){
            updateone(1,1,id,vis[++n]);
        }else if(b[i].op==2){
            updatemul(1,1,id,vis[b[i].pos],vis[b[i].pos]+siz[b[i].pos],b[i].w);
        }else {
            printf("%d\n",query(1,1,id,vis[b[i].pos]));
        }
    }
    return 0;
}
全部评论

相关推荐

01-01 10:21
门头沟学院 Java
谁懂啊!我实习遇到的公司,真的太把实习生当正式员工使唤了,刚入职没几天,连项目代码结构都没摸透,就被安排写项目了!一开始都是些接口对接、数据格式转换的基础活,听起来不难,但架不住我对项目的业务逻辑、代码规范一窍不通。对着前辈丢过来的需求文档,我一边查代码注释,一边翻技术文档,磕磕绊绊写完功能,也只知道&nbsp;“这么写能跑通”,根本不明白&nbsp;“为什么要这么设计”,妥妥的知其然不知其所以然。本以为这种基础活会干很久,结果没过多久,领导直接甩给我一个小功能的开发方案,让我负责从方案落地到功能对接、测试上线的全流程。当时我直接懵了,硬着头皮啃需求、画流程图、写核心代码,遇到不懂的就逮着前辈狂问,加班加点成了家常便饭。更没想到的是,后面居然让我独立负责一个模块的开发,还要做性能优化。从数据库索引调整,到接口响应速度提升,每一步都得自己琢磨、自己验证。那段时间真的累到飞起,每天下班脑子都是懵的尤其是发版的时候,我比谁都紧张,盯着监控屏大气不敢喘,生怕自己写的代码出&nbsp;bug&nbsp;导致系统崩溃。一旦出问题,就得立刻配合运维回滚版本,然后自己留下来加班排查修复,常常整栋办公楼只剩我一个人的工位亮着灯。每天加班到深夜,工作量比正式员工还饱和,我不止一次对着电脑发呆:我到底是来实习的,还是来打工的?虽然这段经历确实让我的技术能力突飞猛进,但那种被推着往前走的疲惫感,直到现在想起来都觉得累。
大家实习都在做什么?
点赞 评论 收藏
分享
01-17 18:15
已编辑
门头沟学院 前端工程师
从上午约我面试然后他迟到,然后中午发消息打电话给我说重约面试时间,我就该意识到。【管理不规范,只是这家公司最小的问题】他妈一个不是技术的人来给我技术面。。。连vvue什么?连react是什么?连普通的HTTP请求是什么?这些东西都不懂的人来给我做技术面,我真的。。。。他妈浪费我40分钟。。一天面了三场,这家公司属实牛逼。不停的问我说上班下班时间谁来派任务公司在哪个区发展怎么样,公司的管理模式什么样,培养机制怎么样带教负责什么。如果出bug了谁来负责。我真的求你了别闹了。我答了15分钟,我已经很不想回答了。然后他就问了我一些很招笑的面试问题。问我前端框架架构设计怎么设计,Websocket可以实现SSE吗??最后还要我硬说,为什么我们公司没转正?为什么?为什么?我说我怎么知道。。这是领导决定,又不是我决定,他说让我分析一下。。。我真的草了,这个人是来搞我的吗?我最后问我说这个没有技术面,他说他就是技术面虽然我今天面的另外两家也很逆天。一个人不停的吹牛,自己100人的公司是全国前几,吹牛了一个小时。我中途几次想跑,真的是底下玩手机在听他那吹牛。。然后最后来了句说,我承诺的东西要实现哦,不然的话,公司会追责的,我我请问我承诺了什么?从头到尾也没有说让我承诺什么。而且我只是作为一个小小的前端卡拉咪,应届生。我要承担什么??好崩溃。。好崩溃的,一天面了三场。两家1000-9999的公司。面试官问的都很傻逼,甚至有些东西我问他估计都答不出来。。&nbsp;我这是在干嘛呀?浪费我一天的时间,我的奶奶。。我本来是抱着说我很菜,我要面试中发现自己的问题,现在来看他妈的这三场面试,面试本身就是问题。。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务