【线段树+dfs序 模板】hdu 5692 ,百毒之星A 题目 snacks dfs 序 +线段树维护最大值

其实 讲道理这是一道不难的“裸题”

现在是 凌晨两点 ,不想打太多字,进入正题吧:
题意中文 :
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。

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

为小度熊规划一个路线,使得路线上的价值总和最大。
Input
输入数据第一行是一个整数T(T≤10),表示有T组测试数据。

对于每组数据,包含两个整数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零食机的路线中,价值总和的最大值。

用dfs序 把 这棵树 的所有节点跑出来
那么对于 节点x , 我们 有区间 L[x]—-R[x] , 这之间的就是x 的子树,我们只需要维护 这个区间的最大值就行了, 如果 对于节点x 增加y, 那么我们只需要 对x 的所有子树都+y ,然后维护L[x]—-R[x] 的最大值就行了, 而x 的所有子树 就在L[x]—-(L[x]+R[x])/2 和 -(L[x]+R[x])/2 +1———R[x] 这两个区间里面啊。 这很典型的用线段树 维护啊。

自己手写的 有巨几把多的自己写搓的地方 ,代码中 注释出来了

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define INF 0x7fffffff   //INT_MAX
#define inf 0x3f3f3f3f   //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
bool cmpbig(int a,int b){return a>b;}
bool cmpsmall(int a,int b){return a<b;}
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
const int MAXN=100005;

struct Edge{
    int to;
    int next;
};
Edge edge[MAXN*2];
int head[MAXN];
int tot,cnt;
int R[MAXN],L[MAXN];
void dfs(int u,int pre){
    L[u]=++cnt;
    for(int i=head[u];i!=-1 ; i=edge[i].next){
        int v=edge[i].to;
        if(v==pre) continue;
        dfs(v,u);
    }
    R[u]=cnt;
}
void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
struct segtree{
    int l,r;
    __int64 flag;
    __int64 cnt;
    void add(__int64 val){
        cnt+=val;
        flag+=val;
    }
} st[MAXN*4];
void build(int l,int r,int rt){
    st[rt].cnt=st[rt].flag=0;
    st[rt].l=l;
    st[rt].l=r;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
}
void push_up(int rt){   // 因为每个节点的 x ,其实都已经加到下面的子节点中了;
     st[rt].cnt= max( st[rt*2].cnt , st[rt*2+1].cnt);
}
void push_down(int rt){
     if(st[rt].flag){
         if(st[rt].l==st[rt].r) return;
         st[rt*2].add(st[rt].flag);    // 这里怎么可能去加 st[rt].cnt????我真是醉了
         st[rt*2+1].add(st[rt].flag);
         st[rt].flag=0;
     }
}
void up(int p,int l,int r,int rt,__int64 val){
    int left=L[p];
    int rig=R[p];
    if(left<=l && r<=rig){
//        printf("befor p %d %d %I64d\n",p,rt,st[rt].cnt);
        st[rt].add(val);//  去更改  st[p] 是不是傻逼???
//        printf("after p %d %d %I64d\n",p,rt,st[rt].cnt);
        return;
    }
    push_down(rt);
    int mid=(l+r)>>1;
    if(mid>=rig)  up(p,l ,  mid,rt*2 , val);
    else if(mid< left) up(p,mid+1,r ,rt*2+1,val);
    else{
        up(p,l ,  mid,rt*2 , val);up(p,mid+1,r ,rt*2+1,val);
    }
    push_up(rt);
}
__int64 ask(int p,int l,int r,int rt){
    int left=L[p];
    int rig=R[p];
    if(left<=l && r <=rig){
        return st[rt].cnt;
    }
    push_down(rt);
    int mid=(l+r)>>1;
    __int64 ans;   // 这里怎么可能写 st[rt].cnt呢, 只有节点上的值是我们要取得
    if(mid>=rig)  ans=ask(p,l ,  mid,rt*2) ;
    else if(mid< left) ans=ask(p,mid+1,r ,rt*2+1);
    else ans=max(ask(p,mid+1,r ,rt*2+1),ask(p,l ,  mid,rt*2) );
    push_up(rt);
    return ans;
}
int f[MAXN];
void init(){
    memset(head,-1,sizeof(head));
    tot=cnt=0;
}
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d",&t);
    for(int k=1;k<=t;k++){
        init();
        printf("Case #%d:\n",k);
        int n,m,i;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        for( i=1;i<n;i++){
            int a,b;
            scanf("%d %d",&a,&b);a++,b++;
            addedge(a,b);
            addedge(b,a);
        }
        dfs(1,0);
        for( i=1;i<=n;i++){
            scanf("%d",&f[i]);
            up(i,1,n,1,f[i]);
        }
        while(m--){
            int op;
            scanf("%d",&op);
            int x;
            scanf("%d",&x);x++;
            if(op){
                printf("%I64d\n",ask(x,1,n,1));
            }
            else{
                int y;
                scanf("%d",&y);
                up(x,1,n,1,y-f[x]);  //这个地方用 i 我也真是醉了
                f[x]=y;
            }
        }
    }
}

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
*/
阅读更多
个人分类: 线段树 DFS
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭