牛客练习赛56 D.小翔和泰拉瑞亚 线段树
Posted kaka0010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客练习赛56 D.小翔和泰拉瑞亚 线段树相关的知识,希望对你有一定的参考价值。
原题链接:https://ac.nowcoder.com/acm/contest/3566/D
题意
有n个数组成的序列,你有m种操作,每次选择 [ l , r ] [l,r] [l,r]区间减去w,你可以从m次操作中任意选择一些操作完成,求完成后整个序列的最大最小值之差最大是多少
分析
首先可以枚举每个数,尽量使它的值减少,用掉所有包含该位置的操作,然后求出全局的最高位置,用最高位置与当前枚举到的位置的高度差来更新答案。这样必定能够求到最优解。因此我们对询问按照左端点进行排序,当操作区间左端点小于当前位置就加入该区间到堆中,最后我们看堆顶的区间右端点是否小于当前位置,小于就直接出堆,每个位置更新一次答案,保证最优性。
Code
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 1e6 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 998244353;
struct node {
int l, r;
ll maxx, minn, tag;
}t[N<<2];
int a[N];
void push_up(int u) {
t[u].maxx = max(t[u<<1].maxx, t[u<<1|1].maxx);
t[u].minn = min(t[u<<1].minn, t[u<<1|1].minn);
}
void push_down(int u) {
if (t[u].tag) {
t[u<<1].tag += t[u].tag;
t[u<<1|1].tag += t[u].tag;
t[u<<1].maxx += t[u].tag;
t[u<<1|1].maxx += t[u].tag;
t[u<<1].minn += t[u].tag;
t[u<<1|1].minn += t[u].tag;
t[u].tag = 0;
return;
}
}
void build(int u, int l, int r) {
t[u].l = l, t[u].r = r, t[u].maxx = -1e18, t[u].minn = 1e18;
if (l == r) {
t[u].maxx = t[u].minn = a[l];
return;
}
int mid = (l + r) >> 1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
push_up(u);
}
void modify(int u, int ql, int qr, int val) {
if (ql <= t[u].l && qr >= t[u].r) {
t[u].maxx += val;
t[u].minn += val;
t[u].tag += val;
return;
}
push_down(u);
int mid = (t[u].l + t[u].r) >> 1;
if (ql <= mid) modify(u<<1, ql, qr, val);
if (qr > mid) modify(u<<1|1, ql, qr, val);
push_up(u);
}
ll query(int u, int ql, int qr) {
if (ql <= t[u].l && qr >= t[u].r) return t[u].maxx;
push_down(u);
int mid = (t[u].l + t[u].r) >> 1;
ll ans = -1e18;
if (ql <= mid) ans = max(ans, query(u<<1, ql, qr));
if (qr > mid) ans = max(ans, query(u<<1|1, ql, qr));
return ans;
}
struct Query {
int l, r, w;
bool operator < (const Query &rhs) const {
return l < rhs.l;
}
}q[M];
struct Node {
int l, r, w;
bool operator < (const Node &rhs) const {
return r > rhs.r;
}
};
void solve() {
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
for (int i = 1; i <= m; i++) cin >> q[i].l >> q[i].r >> q[i].w;
sort(q+1, q+m+1);
priority_queue<Node> que;
int cnt = 1;
ll ans = 0;
for (int i = 1; i <= n; i++) {
while (q[cnt].l <= i && cnt <= m) {
modify(1, q[cnt].l, q[cnt].r, -q[cnt].w);
que.push({q[cnt].l, q[cnt].r, q[cnt].w});
cnt++;
}
ans = max(ans, query(1, 1, n) - query(1, i, i));
while (que.size() && que.top().r <= i) {
modify(1, que.top().l, que.top().r, que.top().w), que.pop();
}
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
以上是关于牛客练习赛56 D.小翔和泰拉瑞亚 线段树的主要内容,如果未能解决你的问题,请参考以下文章