9-3(线段树维护最大最小值)

本文介绍了解决HDU5861Road问题的方法,该问题涉及多个村庄之间的运输计划,目标是最小化未来几天内开放特定路段的总费用。采用区间树的数据结构来维护每段路的开销,并通过更新和查询操作实现最优路径选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HDU 5861 Road

There are n villages along a high way, and divided the high way into n-1 segments. Each segment would charge a certain amount of money for being open for one day, and you can open or close an arbitrary segment in an arbitrary day, but you can open or close the segment for just one time, because the workers would be angry if you told them to work multiple period.

We know the transport plan in the next m days, each day there is one cargo need to transport from village aiai to village bibi, and you need to guarantee that the segments between aiai and bibi are open in the i-th day. Your boss wants to minimize the total cost of the next m days, and you need to tell him the charge for each day.

(At the beginning, all the segments are closed.)

Input

Multiple test case. For each test case, begins with two integers n, m(1<=n,m<=200000), next line contains n-1 integers. The i-th integer wiwi(1<=wiwi<=1000) indicates the charge for the segment between village i and village i+1 being open for one day. Next m lines, each line contains two integers ai,bi(1≤ai,bi<=n,ai!=bi)ai,bi(1≤ai,bi<=n,ai!=bi).

Output

For each test case, output m lines, each line contains the charge for the i-th day.

Sample Input

4 3
1 2 3
1 3
3 4
2 4

Sample Output

3
5
5

#include <bits/stdc++.h>
using namespace std;
int n, m;
const int maxn = 200010;
const int INF = 0x3f3f3f3f;
int cost[maxn];
vector<int> vec_s[maxn], vec_t[maxn];
struct Tree{
    int l, r, ddl;
    int open;
}tree[maxn*5];

void build(int node){
    tree[node].ddl = 0;
    tree[node].open = INF;
    if(tree[node].l == tree[node].r) return ;
    int mid = (tree[node].l + tree[node].r)/2;
    tree[node*2].l = tree[node].l;
    tree[node*2].r = mid;
    tree[node*2+1].l = mid+1;
    tree[node*2+1].r = tree[node].r;
    build(node*2);
    build(node*2+1);
}

void pushdown(int node){
    tree[node*2].ddl = max(tree[node*2].ddl, tree[node].ddl);
    tree[node*2+1].ddl = max(tree[node*2+1].ddl, tree[node].ddl);
    tree[node*2].open = min(tree[node*2].open, tree[node].open);
    tree[node*2+1].open = min(tree[node*2+1].open, tree[node].open);
}

void update(int node, int s, int e, int c){
    if(s <= tree[node].l && tree[node].r <= e){
        if(tree[node].l != tree[node].r) pushdown(node);
        tree[node].ddl = max(tree[node].ddl, c);
        tree[node].open = min(tree[node].open, c);
        return;
    }
    pushdown(node);
    int mid = (tree[node].l + tree[node].r) / 2;
    if(s <= mid)
        update(node*2, s, e, c);
    if(e > mid)
        update(node*2+1, s, e, c);

    tree[node].open = max(tree[node*2].open, tree[node*2+1].open);
    tree[node].ddl = min(tree[node*2].ddl, tree[node*2+1].ddl);
    return;
}

void query(int node, int &tar, int& s, int& t){
    if(tree[node].l == tree[node].r && tree[node].l == tar){
        s = tree[node].open;
        t = tree[node].ddl;
        if(s == INF) s = t = 0;
        return;
    }
    pushdown(node);
    int mid = (tree[node].l + tree[node].r)/2;
    if(tar <= mid)
        query(node*2, tar, s, t);
    else 
        query(node*2+1, tar, s, t);
}

int main()
{
    while(cin >> n >> m){
        for(int i = 1; i < n; i++){
            scanf("%d", &cost[i]);
        }

        tree[1].l = 1, tree[1].r = n-1;
        build(1);
        for(int i = 1; i <= m; i++){
            vec_s[i].clear(), vec_t[i].clear();
            int s, e;
            scanf("%d%d", &s, &e);
            if(s>e) swap(s, e);   //题目没说这里的s 一定小于 e 啊!!!!!!
            update(1, s, e-1, i);
        }
        for(int i = 1; i <= n-1; i++){
            int s = 0, t = 0;
            query(1, i, s, t);
            vec_s[s].push_back(i);
            vec_t[t].push_back(i);
        }
        int sum = 0;
        for(int i = 1; i <= m; i++){
            for(int j = 0; j < vec_s[i].size(); j++){
                sum += cost[vec_s[i][j]];
            }
            printf("%d\n", sum);
            for(int j = 0; j < vec_t[i].size(); j++)
                sum -= cost[vec_t[i][j]];
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值