PTA-森森快递
贪心的话就不用讲了,实现快速查找线段树也少不了,让人头大的是区间更新不比单点更新,要是用一般方法肯定就超时了,然后就学会用lazy数组优化,具体内容见代码注释
AC代码
#include "bits/stdc++.h"
#define ll long long
#define P pair<int, int>
using namespace std;
const int N = 1e7 + 10;
int tree[N];
int arr[N];
int lazy[N];
vector<P> v;
bool cmp(P a, P b){
if(a.second != b.second) {
return a.second < b.second;
}
return a.first < b.first;
}
void build(int root, int left, int right) {
if(left == right){
tree[root] = arr[left];
return;
}
int mid = (left + right) / 2;
int lchild = root * 2; // 咱们记根节点从1开始
int rchild = root * 2 + 1;
build(lchild, left, mid);
build(rchild, mid + 1, right);
tree[root] = min(tree[lchild], tree[rchild]);
}
void push_down(int root) { // 咱们就叫他向下传递
int lchild = root * 2;
int rchild = root * 2 + 1;
tree[lchild] += lazy[root]; // 赋值传递
tree[rchild] += lazy[root];
lazy[lchild] += lazy[root]; // 标记传递
lazy[rchild] += lazy[root];
lazy[root] = 0; // 完成任务, 标记取消
}
void update(int root, int left, int right, int need_l, int need_r, int val){
if(need_l <= left && right <= need_r){
lazy[root] += val;
tree[root] += val; // 咱们先不要管, 这个当然不对, 但是查询的时候的更新为正确值, 打上标记
return;
}
if(right < need_l || left > need_r){
return; // 当前区间不在更新范围, 直接退出
}
if(lazy[root] != 0) push_down(root); // 关键, 给标记过的值向下传递, 内容不更新的话值仍然为错误值
int mid = (left + right) / 2;
int lchild = root * 2;
int rchild = root * 2 + 1;
update(lchild, left, mid, need_l, need_r, val);
update(rchild, mid + 1, right, need_l, need_r, val);
tree[root] = min(tree[lchild], tree[rchild]);
}
ll query(int root, int left, int right, int need_l, int need_r){
if(need_l <= left && need_r >= right){
return tree[root];
}
if(need_l > right || need_r < left){
return LONG_LONG_MAX; // 最后一个样例大于INT_MAX,不能用0x3f3f3f3f
}
if(lazy[root] != 0) push_down(root);
int mid = (left + right) / 2;
int lchild = root * 2;
int rchild = root * 2 + 1;
ll l_come = query(lchild, left, mid, need_l, need_r);
ll r_come = query(rchild, mid + 1, right, need_l, need_r);
return min(l_come, r_come);
}
int main(){
int n, m;
cin>>n>>m;
for(int i = 1; i < n; i ++){
cin>>arr[i];
}
for(int i = 0; i < m; i++){
int x, y;
cin>>x>>y;
if(x > y) swap(x, y);
v.push_back({x, y});
}
build(1, 1, n - 1);
sort(v.begin(), v.end(), cmp);
ll res = 0;
for(int i = 0; i < v.size(); i++){
// v[i].first + 1, 仔细推推就出来了
ll val = query(1, 1, n - 1, v[i].first + 1, v[i].second);
res += val;
update(1, 1, n - 1, v[i].first + 1, v[i].second, -val);
}
cout<<res<<endl;
return 0;
}