スナックdfs注文+ラインセグメントツリー

ポータル

タイトル説明

Baidu Science Parkにはn台のスナックマシンがあり、スナックマシンはn-1本の道路で相互に接続されています。各スナックマシンの値はvで、XiaoduBearにスナックを提供する価値を表します。

スナックは頻繁に消費され、補充されるため、スナックマシンの値vは時々変化します。Xiaodu Xiongは、番号0のスナックマシンからのみ開始でき、各スナックマシンは最大で1回通過します。さらに、Xiaodu Xiongは特定のスナックマシンのスナックを優先し、スナックマシンがルート上にある必要があります。

ルートの合計値を最大化するために、XiaoduBearのルートを計画します。

分析

この質問では、ツリー構造をチェーン構造に変換して次のノードから各ノードまでの距離を維持し、次にラインセグメントを使用して間隔の最大値を維持し、ポイントの値を変更できます。実際、このポイントとこの時点でのサブツリーの変更も間隔の変更に変換されるため、dfsを使用してこのツリーをチェーンに変換し、ラインセグメントツリーを使用して間隔のクエリと変更を実行できます。

コード

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const ll INF = 0x3f3f3f3f3f3f;
const int N = 100010;
int h[N],ne[N * 2],e[N * 2],idx;
ll d[N],s[N];
int in[N],out[N];
int n,m;
int cnt;

struct Node{
    
    
    int l,r;
    ll sum,add;
}tr[N << 2];

void add(int x,int y){
    
    
    ne[idx] = h[x],e[idx] = y,h[x] = idx++;
}

void dfs(int u,int fa,ll pp){
    
    
    in[u] = ++cnt;
    d[cnt] = pp;
    for(int i = h[u];~i;i = ne[i]){
    
    
        int j = e[i];
        if(j == fa) continue;
        dfs(j,u,pp + s[j]);
    }
    out[u] = cnt;
}

void pushup(int u){
    
    
    tr[u].sum = max(tr[u << 1].sum,tr[u << 1 | 1].sum);
}

void down(int u){
    
    
    auto &f = tr[u],&l = tr[u << 1],&r = tr[u << 1 | 1];
    if(f.add){
    
    
        l.add += f.add,l.sum += f.add;
        r.add += f.add,r.sum += f.add;
        f.add = 0;
    }
}

void build(int u,int l,int r){
    
    
    tr[u].l = l,tr[u].r = r,tr[u].add = 0;
    if(l == r){
    
    
        tr[u].sum = d[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1,l,mid);
    build(u << 1 | 1,mid + 1,r);
    pushup(u);
}

void modify(int u,int l,int r,ll x){
    
    
    if(tr[u].l >= l && tr[u].r <= r){
    
    
        tr[u].sum += x;
        tr[u].add += x;
        return;
    }
    down(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(l <= mid) modify(u << 1,l,r,x);
        if(r > mid) modify(u << 1 | 1,l,r,x);
    pushup(u);
}

ll query(int u,int l,int r){
    
    
    if(tr[u].l >= l && tr[u].r <= r){
    
    
        return tr[u].sum;
    }
    down(u);
    int mid = tr[u].l + tr[u].r >> 1;
    ll ans = -INF;
    if(l <= mid) ans = query(u << 1,l,r);
    if(r > mid) ans = max(query(u << 1 | 1,l,r),ans);
    return ans;
}


int main(){
    
    
    int t;
    scanf("%d",&t);
    for(int ppp = 1;ppp <= t;ppp++){
    
    
        memset(h,-1,sizeof h);
        idx = cnt = 0;
        scanf("%d%d",&n,&m);
        printf("Case #%d:\n",ppp);
        for(int i = 1;i < n;i++){
    
    
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        for(int i = 0;i < n;i++) scanf("%lld",&s[i]);
        dfs(0,-1,s[0]);
        build(1,1,n);
        while(m--){
    
    
            int op,x,y;
            scanf("%d%d",&op,&x);
            if(!op){
    
    
                scanf("%d",&y);
                ll add = 1ll * y - s[x];
                modify(1,in[x],out[x],add);
                s[x] = y;
            }
            else printf("%lld\n",query(1,in[x],out[x]));
        }
    }
}

おすすめ

転載: blog.csdn.net/tlyzxc/article/details/111054103