hdu-5692 Snacks(dfs序+线段树)

题目链接:

Snacks

Problem Description

百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。

由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。

为小度熊规划一个路线,使得路线上的价值总和最大。

Input

输入数据第一行是一个整数T(T≤10),表示有TT组测试数据。

对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。

接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。

接下来一行由n个数组成,表示从编号为0到编号为n-1的零食机的初始价值v(∣v∣<100000)。

接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:

#pragma comment(linker, "/STACK:1024000000,1024000000")

Output

对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。

对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

Sample Input

1
6 5
0 1
1 2
0 3
3 4
5 3
7 -5 100 20 -5 -7
1 1
1 3
0 2 -1
1 1
1 5

Sample Output

Case #1:
102
27
2
20

题意:

思路:

先把这棵树dfs求出距离并弄成线段树,l[x],r[x]分别表示x的子树节点的左右区间,每次修改[l[x],r[x]]这个区间,用线段树的区间修改,然后就好啦;

AC代码:
#include <bits/stdc++.h>
/*
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio>
*/
using namespace std;
#define Riep(n) for(int i=1;i<=n;i++)
#define Riop(n) for(int i=0;i<n;i++)
#define Rjep(n) for(int j=1;j<=n;j++)
#define Rjop(n) for(int j=0;j<n;j++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef long long LL;
const LL mod=1e9+7;
const double PI=acos(-1.0);
const LL inf=1e18;
const int N=1e5+4;
int n,m,head[N],l[2*N],r[2*N],cnt,num;
LL dis[N],b[N],va[N];
struct Edge
{
    int to,next;
}edge[2*N];
void add_edge(int s,int e)
{
    edge[cnt].next=head[s];
    edge[cnt].to=e;
    head[s]=cnt++;
}
void  dfs(int x,int fa)
{
    num++;
    b[num]=dis[x];
    l[x]=num;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int y=edge[i].to;
        if(y!=fa)
        {
            dis[y]=dis[x]+va[y];
            dfs(y,x);
        }
    }
    r[x]=num;
}
struct Tree
{
    int l,r;
    LL ans,lazy;
}tr[4*N];
void pushup(int o)
{
    tr[o].ans=max(tr[2*o].ans,tr[2*o+1].ans);
}
void pushdown(int o)
{
    if(tr[o].lazy)
    {
        tr[2*o].ans+=tr[o].lazy;
        tr[2*o+1].ans+=tr[o].lazy;
        tr[2*o].lazy+=tr[o].lazy;
        tr[2*o+1].lazy+=tr[o].lazy;
        tr[o].lazy=0;
    }
}
void build(int o,int L,int R)
{
    tr[o].l=L;
    tr[o].r=R;
    tr[o].lazy=0;
    if(L>=R)
    {
        tr[o].ans=b[L];
        return ;
    }
    int mid=(L+R)>>1;
    build(2*o,L,mid);
    build(2*o+1,mid+1,R);
    pushup(o);
}
void update(int o,int L,int R,LL val)
{
    if(L<=tr[o].l&&R>=tr[o].r)
    {
        tr[o].ans=tr[o].ans+val;
        tr[o].lazy=tr[o].lazy+val;
        return ;
    }
    int mid=(tr[o].l+tr[o].r)>>1;
    pushdown(o);
    if(R<=mid)update(2*o,L,R,val);
    else if(L>mid)update(2*o+1,L,R,val);
    else
    {
        update(2*o,L,mid,val);
        update(2*o+1,mid+1,R,val);
    }
    pushup(o);
}
LL query(int o,int L,int R)
{
    if(L<=tr[o].l&&tr[o].r<=R)return tr[o].ans;
    int mid=(tr[o].l+tr[o].r)>>1;
    pushdown(o);
    if(R<=mid)return query(o*2,L,R);
    else if(L>mid)return query(o*2+1,L,R);
    else return max(query(2*o,L,mid),query(2*o+1,mid+1,R));
}
int main()
{
      int t;
      scanf("%d",&t);
      int Case=1;
      while(t--)
      {
          printf("Case #%d:\n",Case++);
          cnt=0;
          num=0;
          mst(head,-1);
          scanf("%d%d",&n,&m);
          int u,v;
          Riep(n-1)
          {
              scanf("%d%d",&u,&v);
              add_edge(u,v);
              add_edge(v,u);
          }
          Riop(n)scanf("%I64d",&va[i]);
          dis[0]=va[0];
          dfs(0,-1);
          build(1,1,num);
          int flag,x,y;
          Riep(m)
          {
              scanf("%d",&flag);
              if(flag)
              {
                  scanf("%d",&x);
                  printf("%I64d\n",query(1,l[x],r[x]));
              }
              else
              {
                  scanf("%d%d",&x,&y);
                  update(1,l[x],r[x],(LL)y-va[x]);
                  va[x]=(LL)y;
              }
          }
      }
    return 0;
}
时间: 2024-07-30 04:13:59

hdu-5692 Snacks(dfs序+线段树)的相关文章

hdu 5692 Snacks(dfs时间戳+线段树)

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2165    Accepted Submission(s): 513 Problem Description 百度科技园内有n个零食机,零食机之间通过n?1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发

HDU5692 Snacks DFS序 线段树

题目 HDU5692 Snacks Problem Description 百度科技园内有n个零食机,零食机之间通过n?1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机. 为小度熊规划一个路线,使得路线上的价值总和最大. Input 输入数据第一行是一个整数T(T≤10),表示有T组测试数

HDU 4366 Successor( DFS序+ 线段树 )

Successor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2631    Accepted Submission(s): 634 Problem Description Sean owns a company and he is the BOSS.The other Staff has one Superior.every st

POJ 3321 DFS序+线段树

单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include <cstdio> 6: #include <cstring> 7: #include <cctype> 8: #include <algorithm> 9: #include <vector> 10: #include <iostream> 1

codevs1228 (dfs序+线段树)

总结: 第一次遇到dfs序的问题,对于一颗树,记录节点 i 开始搜索的序号 Left[i] 和结束搜索的序号 Righti[i],那么序号在 Left[i] ~ Right[i] 之间的都是节点 i 子树上的节点. 并且此序号与线段树中 L~R 区间对应,在纸上模拟了几遍确实如此,但暂时还未理解为何对应. 此题就是dfs序+线段树的裸题 代码: #include<iostream> #include<vector> #include<cstring> #include&

[BZOJ 3306]树(dfs序+线段树+倍增)

Description 给定一棵大小为 n 的有根点权树,支持以下操作: • 换根 • 修改点权 • 查询子树最小值 Solution 单点修改子树查询的话可以想到用dfs序+线段树来处理,换根的处理画一画图应该可以明白: 如果查询的x是当前的根rt,直接返回整棵树的min 如果rt在x的子树中,用倍增的方法找到离x最近的rt的祖先t,整棵树除t的子树以外的部分就是x当前根下的子树 如果rt不在x的子树中,查询x原来的子树的min值 #include<iostream> #include<

Educational Codeforces Round 6 E dfs序+线段树

题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili上电子科技大学发的视频学习的 将一颗树通过dfs编号的方式 使每个点的子树的编号连在一起作为相连的区间 就可以配合线段树搞子树 因为以前好像听说过 线段树可以解决一种区间修改和查询区间中不同的xx个数...所以一下子就想到了... 但是我不会写线段树..只会最简单的单点修改区间查询...不会用延迟标

【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景.所有场景和选择支构成树状结构:开始游戏时在根节点(共通线)

【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\),问你答案是多少. \(n\leq {10}^5,k\leq {10}^9\) 题解 设\(l\)为这棵树的叶子个数,显然当\(k>\)树的深度时答案都是\(l\). 下面要证明:答案是\(O(l+\frac{n-l}{k})\)的. 我们从下往上贪心,每次选择一个未被覆盖的深度最深的点,覆盖这个点网