题解:P12013 [Ynoi April Fool's Round 2025] 牢夸
Claire0918 · · 题解
我们作出猜想:最优的
我们先说明一个引理:如果
证明:
设
考虑反证法,假设原命题不成立,也就是说
移项
两式相加
这显然是错误的,从而假设不成立,原命题得证。
对于一个长度大于
记
使用线段树维护
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a));
using namespace std;
const int maxn = 1e6 + 10;
struct{
struct{
int l, r;
long long value, tag;
} tree[maxn << 2];
inline void build(int index, int l, int r){
tree[index].l = l, tree[index].r = r;
if (l == r){
return;
}
const int mid = l + r >> 1;
build(index << 1, l, mid), build(index << 1 | 1, mid + 1, r);
}
inline void basic_add(int index, long long k){
tree[index].value += k, tree[index].tag += k;
}
inline void pushup(int index){
tree[index].value = max(tree[index << 1].value, tree[index << 1 | 1].value);
}
inline void pushdown(int index){
basic_add(index << 1, tree[index].tag), basic_add(index << 1 | 1, tree[index].tag), tree[index].tag = 0;
}
inline void modify(int index, int l, int r, long long k){
if (l <= tree[index].l && r >= tree[index].r){
basic_add(index, k);
return;
}
pushdown(index);
const int mid = tree[index].l + tree[index].r >> 1;
if (l <= mid){
modify(index << 1, l, r, k);
}
if (r > mid){
modify(index << 1 | 1, l, r, k);
}
pushup(index);
}
inline long long query(int index, int l, int r){
if (l <= tree[index].l && r >= tree[index].r){
return tree[index].value;
}
pushdown(index);
const int mid = tree[index].l + tree[index].r >> 1;
long long res = -1e18;
l <= mid && (res = max(res, query(index << 1, l, r)));
r > mid && (res = max(res, query(index << 1 | 1, l, r)));
return res;
}
} seg2, seg3;
int n, q;
long long a[maxn], a2[maxn], a3[maxn];
int main(){
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
i >= 2 && (a3[i] = (a2[i] = a[i] + a[i - 1]) + a[i - 2]);
}
a2[1] = a3[1] = a3[2] = -1e18;
seg2.build(1, 1, n), seg3.build(1, 1, n);
for (int i = 1; i <= n; i++){
seg2.modify(1, i, i, a2[i]), seg3.modify(1, i, i, a3[i]);
}
while (q--){
int op, l, r;
scanf("%d %d %d", &op, &l, &r);
if (op == 1){
long long x;
scanf("%lld", &x);
seg2.modify(1, l, l, x), seg3.modify(1, l, l, x);
if (l + 1 <= r){
seg2.modify(1, l + 1, r, x << 1), seg3.modify(1, l + 1, l + 1, x << 1);
}
if (r + 1 <= n){
seg2.modify(1, r + 1, r + 1, x), seg3.modify(1, r + 1, r + 1, l == r ? x : x << 1);
}
if (l + 2 <= r){
seg3.modify(1, l + 2, r, x * 3);
}
if (r + 2 <= n){
seg3.modify(1, r + 2, r + 2, x);
}
}else{
const long long res2 = seg2.query(1, l + 1, r), res3 = (l + 2 <= r ? seg3.query(1, l + 2, r) : -1e18);
long long res = res2 * 3 > res3 << 1 ? res2 : res3;
int len = res2 * 3 > res3 << 1 ? 2 : 3;
res % len || (res /= len, len = 1);
printf("%lld/%d\n", res, len);
}
}
return 0;
}