10.CF515E Drazil and Park 简单线段树


给定一个环,10.CF515E Drazil and Park 简单线段树_i++之间的距离给定,每个点有点权10.CF515E Drazil and Park 简单线段树_i++_02
每次询问会禁止经过一个区间,求两个点10.CF515E Drazil and Park 简单线段树_i++_03能够使得10.CF515E Drazil and Park 简单线段树_c++_04取得最大值
求这个最大值

洛谷传送门:​​CF515E Drazil and Park - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)​

CF传送门:​​E. Drazil and Park (codeforces.com)​

题目分析

  • 给定一个环,10.CF515E Drazil and Park 简单线段树_i++_05之间的距离给定,每个点有点权10.CF515E Drazil and Park 简单线段树_算法_06
  • 每次询问会禁止经过一个区间,求两个点10.CF515E Drazil and Park 简单线段树_算法_07能够使得10.CF515E Drazil and Park 简单线段树_#define_08取得最大值
  • 求这个最大值

把式子转化一下:

  • 10.CF515E Drazil and Park 简单线段树_算法_09求前缀和10.CF515E Drazil and Park 简单线段树_#define_10,则10.CF515E Drazil and Park 简单线段树_数据结构_11
  • 原式化为10.CF515E Drazil and Park 简单线段树_i++_12
  • 10.CF515E Drazil and Park 简单线段树_数据结构_13维护区间最大值,对10.CF515E Drazil and Park 简单线段树_算法_14维护区间最小值即可

于是就变成了线段树维护区间最大值最小值的过程。在计算过程中对答案取最大值即可。

Code

#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl '\n'
using namespace std;

namespace ffastIO {
const int bufl = 1 << 15;
char buf[bufl], *s = buf, *t = buf;
inline int fetch() {
if (s == t) { t = (s = buf) + fread(buf, 1, bufl, stdin); if (s == t) return EOF; }
return *s++;
}
inline int read() {
int a = 0, b = 1, c = fetch();
while (!isdigit(c))b ^= c == '-', c = fetch();
while (isdigit(c)) a = a * 10 + c - 48, c = fetch();
return b ? a : -a;
}
}

const int N = 2e5 + 10, MOD = 1e9 + 7;
int d[N << 1], h[N << 1], s[N << 1], n, m;

int sum(int l, int r){
if(l <= r) return h[r] - h[l - 1];
else return h[l + n] - h[r - 1];
}

int dist(int l, int r){
if(l <= r) return d[r] - d[l - 1];
else return d[l + n] - d[r - 1];
}

namespace SegTree{
#define ls rt << 1
#define rs rt << 1 | 1
#define lson ls, l,
#define rson rs, mid + 1,
#define tii tuple<int, int, int>
int maxx[N << 2], minn[N << 2], ans[N << 2];

inline void push_up(int rt){
maxx[rt] = max(maxx[ls], maxx[rs]);
minn[rt] = max(minn[ls], minn[rs]);
ans[rt] = max({minn[ls] + maxx[rs], ans[ls], ans[rs]});
}

void build(int rt, int l, int r){
if(l == r){
maxx[rt] = s[l - 1] + h[l];
minn[rt] = -s[l - 1] + h[l];
return;
}
int mid = l + r >> 1;
build(lson), build(rson);
push_up(rt);
}

tii query(int rt, int l, int r, int L, int R){
if(l >= L && r <= R) return tii{maxx[rt], minn[rt], ans[rt]};
int mid = l + r >> 1; tii ans1, ans2; bool flag1 = false, flag2 = false;
if(mid >= L) flag1 = true, ans1 = query(lson, L, R);
if(mid < R) flag2 = true, ans2 = query(rson, L, R);
if(flag1 && flag2){
return tii{max(get<0>(ans1), get<0>(ans2)), max(get<1>(ans1), get<1>(ans2)), max({get<1>(ans1) + get<0>(ans2), get<2>(ans1), get<2> (ans2)})};
}
else if(flag1) return ans1;
else return ans2;
}

}

#define SEGRG 1, 1,

inline void solve(){
n = ffastIO::read(), m = ffastIO::read();
for(int i = 1; i <= n; i++) d[i] = d[i + n] = ffastIO::read();
for(int i = 1; i <= n; i++) h[i] = h[i + n] = ffastIO::read() * 2;
n *= 2;
for(int i = 1; i <= n; i++) s[i] = s[i - 1] + d[i];
// for(int i = 1; i <= n; i++) cout << d[i] << " \n"[i == n * 2];
// for(int i = 1; i <= n; i++) cout << h[i] << " \n"[i == n * 2];
SegTree::build(SEGRG);
for(int i = 1; i <= m; i++){
int l = ffastIO::read(), r = ffastIO::read();
if(l <= r) cout << get<2>(SegTree::query(SEGRG, r + 1, l + (n >> 1) - 1)) << endl;
else cout << get<2>(SegTree::query(SEGRG, r + 1, l - 1)) << endl;
}
}

signed main(){
int t = 1; // cin >> t;
while(t--) solve();
return 0;
}