hdu5642 snake(dfs序+线段树)(模板)

Snacks

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 7726    Accepted Submission(s): 1681


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

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

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

 

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

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

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

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

接下来m 行,有两种操作:0 x y ,表示编号为x 的零食机的价值变为y1 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
 
 
 
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
typedef long long ll;
int n,m; 
const int N=1e5+10;
ll a[N];
vector<int> G[N*3];
int R[N];
int L[N];
ll val[N];
ll cost[N];


struct Tree{
    ll c,add;
    int l,r;
    #define c(x) t[x].c
    #define l(x) t[x].l
    #define r(x) t[x].r
    #define add(x) t[x].add    
}t[N<<4];
 
void build(int p,int l,int r){
    l(p)=l;r(p)=r;add(p)=0;
    if(l==r){
        c(p)=val[l];
        return;
    }
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    c(p)=max(c(p*2),c(p*2+1));
}

int ct=0;

void dfs(int now,int pre){
    L[now]=++ct;
    val[L[now]]=val[L[pre]]+a[now];
    for(int i=0;i<G[now].size();i++){
        int u=G[now][i];
        if(u==pre) continue;
        dfs(u,now);
    }
    R[now]=ct;    
}

 

void spread(int p){
    if(add(p)){
        c(p*2)+=add(p);
        c(p*2+1)+=add(p);
        add(p*2)+=add(p);
        add(p*2+1)+=add(p);
        add(p)=0;
    }
}

void update(int st,int L,int R,ll v)
{
    if(l(st)>=L&&R>=r(st))
    {
        c(st)+=v;
        add(st)+=v;
        return;
    }
    spread(st);
    int mid=(l(st)+r(st))>>1;
    if(L<=mid)
        update(st<<1,L,R,v);
    if(R>mid)
        update(st<<1|1,L,R,v);
    c(st)=max(c(st*2),c(st*2+1));
}
ll query(int st,int L,int R)
{
    if(l(st)>=L&&R>=r(st))
        return c(st);
    ll ans=-1e17-3;
    int mid=(l(st)+r(st))>>1;
    spread(st);
    if(L<=mid)
        ans=max(ans,query(st<<1,L,R));
    if(R>mid)
        ans=max(ans,query(st<<1|1,L,R));
    return ans;
}
 
int main(){
    int ca;
    scanf("%d",&ca);
    int count =1;
    while(ca--){
        ct=0;
        printf("Case #%d:\n",count++);
        scanf("%d%d",&n,&m);
        int ta,tb;
        for(int i=0;i<=n;i++) G[i].clear(); 
        for(int i=1;i<n;i++){
            scanf("%d%d",&ta,&tb);
            ta++;
            tb++;
            G[ta].push_back(tb);
            G[tb].push_back(ta);
        }
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        val[i]=cost[i]=a[i];
    } 
    val[0]=0;
    dfs(1,0);
    build(1,1,n);
    for(int i=1;i<=m;i++){
           int ta,tb;
           scanf("%d%d",&ta,&tb);
           tb++;
           if(ta==0){
               ll tc;
               scanf("%lld",&tc);
               update(1,L[tb],R[tb],tc-a[tb]);
               a[tb]=tc;
           }
        else if(ta==1){
            printf("%lld\n",query(1,L[tb],R[tb]));
        }   
       }        
    } 
}

改了一晚上代码,死于lazy标记没有开long long 

posted @ 2019-10-09 00:17  Ellery_lrh  阅读(142)  评论(0编辑  收藏  举报