P8563 Magenta Potion 题解
1.洛谷 P4969 神秘的703 题解2.洛谷 P8059 [POI2003] Monkeys 题解3.UVA198 Peter's Calculator 题解4.UVA1400 "Ray, Pass me the dishes!" 题解5.UVA11504 Dominos 题解6.P5686 [CSP-S2019 江西] 和积和 题解7.UVA353 Pesky Palindromes 题解8.P1399 [NOI2013] 快餐店 题解9.UVA10091 The Valentine's Day 题解10.题解:P10838 『FLA - I』庭中有奇树11.题解:P10837 『FLA - I』云音泛12.题解:CF437B The Child and Set13.题解:UVA1456 Cellular Network14.题解:P8113 [Cnoi2021] 自我主义的平衡者15.题解:AT_arc147_e [ARC147E] Examination16.P8564 ρars/ey 题解
17.P8563 Magenta Potion 题解
18.P8474 「GLR-R3」立春 题解19.P8475 「GLR-R3」雨水 题解20.题解:P4288 [SHOI2014] 信号增幅仪前排警告
这是较为通用,不需要脑子,但是代码量巨大的题解,请谨慎食用
解题思路
不知道大家做没做过带修改的区间最大连续子段和,这一题其实就是带修改的区间最大连续子段积。
那么其实做法是类似的。
我们用线段树维护五个量:当前区间答案,区间前缀最小值,区间前缀最大值,区间后缀最小值,区间后缀最大值。
然后合并的时候分情况讨论:
-
当前答案在左儿子区间内
-
当前答案在右儿子区间内
-
当前答案跨左,右儿子的区间
前两种情况直接得,最后一种情况就是左儿子区间的一个后缀称上右儿子区间的一个前缀的积取最大值。
但是,不同与区间最大连续子段和直接简单相加,由于负负得正,乘法最大值可以通过最大值 最大值,最小值 最小值,最大值 最小值这几种方式来得到,所以维护前缀最小值和后缀最小值。
完整代码
很巨,建议自己打,加强印象。
#include<bits/stdc++.h>
#define MAXN 200010
#define lson now << 1
#define rson now << 1 | 1
#define INF 1073741825
using namespace std;
typedef long long ll;
struct sec{
int l, r;
ll mul;
sec operator * (const sec &b){
sec res;
res.mul = this->mul * b.mul;
res.l = min(this->l, b.l); res.r = max(this->r, b.r);
return res;
}
};
struct node{
int l, r;
sec max_pre, min_pre, max_lst, min_lst, max_res;
};
bool operator > (sec a, sec b){ return a.mul > b.mul; }
bool operator < (sec a, sec b){ return a.mul < b.mul; }
node tree[MAXN << 2];
int n, q;
int a[MAXN];
void push_up(node &now, node &ls, node &rs){
now.max_res = max(ls.max_res, rs.max_res);
now.max_res = max(now.max_res, ls.max_lst * rs.max_pre);
now.max_res = max(now.max_res, ls.min_lst * rs.min_pre);
now.max_res = max(now.max_res, ls.min_lst * rs.max_pre);
now.max_res = max(now.max_res, ls.max_lst * rs.min_pre);
if(ls.max_pre.r == ls.r){
now.max_res = max(now.max_res, ls.max_pre * rs.max_pre);
now.max_res = max(now.max_res, ls.max_pre * rs.min_pre);
}
if(ls.min_pre.r == ls.r){
now.max_res = max(now.max_res, ls.min_pre * rs.min_pre);
now.max_res = max(now.max_res, ls.min_pre * rs.max_pre);
}
if(rs.max_lst.l == rs.l){
now.max_res = max(now.max_res, ls.max_lst * rs.max_lst);
now.max_res = max(now.max_res, ls.min_lst * rs.max_lst);
}
if(rs.min_lst.l == rs.l){
now.max_res = max(now.max_res, ls.min_lst * rs.min_lst);
now.max_res = max(now.max_res, ls.max_lst * rs.min_lst);
}
if(now.max_res.mul >= INF) now.max_res.mul = INF;
now.max_pre = ls.max_pre;
if(ls.max_pre.r == ls.r){
now.max_pre = max(now.max_pre, ls.max_pre * rs.max_pre);
now.max_pre = max(now.max_pre, ls.max_pre * rs.min_pre);
}
if(ls.min_pre.r == ls.r){
now.max_pre = max(now.max_pre, ls.min_pre * rs.min_pre);
now.max_pre = max(now.max_pre, ls.min_pre * rs.max_pre);
}
if(now.max_pre.mul >= INF) now.max_pre.mul = INF;
now.min_pre = ls.min_pre;
if(ls.max_pre.r == ls.r){
now.min_pre = min(now.min_pre, ls.max_pre * rs.max_pre);
now.min_pre = min(now.min_pre, ls.max_pre * rs.min_pre);
}
if(ls.min_pre.r == ls.r){
now.min_pre = min(now.min_pre, ls.min_pre * rs.min_pre);
now.min_pre = min(now.min_pre, ls.min_pre * rs.max_pre);
}
if(now.min_pre.mul <= -INF) now.min_pre.mul = -INF;
now.max_lst = rs.max_lst;
if(rs.max_lst.l == rs.l){
now.max_lst = max(now.max_lst, ls.max_lst * rs.max_lst);
now.max_lst = max(now.max_lst, ls.min_lst * rs.max_lst);
}
if(rs.min_lst.l == rs.l){
now.max_lst = max(now.max_lst, ls.min_lst * rs.min_lst);
now.max_lst = max(now.max_lst, ls.max_lst * rs.min_lst);
}
if(now.max_lst.mul >= INF) now.max_lst.mul = INF;
now.min_lst = rs.min_lst;
if(rs.max_lst.l == rs.l){
now.min_lst = min(now.min_lst, ls.max_lst * rs.max_lst);
now.min_lst = min(now.min_lst, ls.min_lst * rs.max_lst);
}
if(rs.min_lst.l == rs.l){
now.min_lst = min(now.min_lst, ls.min_lst * rs.min_lst);
now.min_lst = min(now.min_lst, ls.max_lst * rs.min_lst);
}
if(now.min_lst.mul <= -INF) now.min_lst.mul = -INF;
}
void build(int now, int l, int r){
tree[now].l = l; tree[now].r = r;
if(tree[now].l == tree[now].r){
tree[now].max_pre = tree[now].max_lst = tree[now].max_res = tree[now].min_pre = tree[now].min_lst = (sec){l, r, a[l]};
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid); build(rson, mid + 1, r);
push_up(tree[now], tree[lson], tree[rson]);
}
void update(int now, int pos, int val){
if(tree[now].l == pos && tree[now].r == pos){
tree[now].max_pre = tree[now].max_lst = tree[now].max_res = tree[now].min_pre = tree[now].min_lst = (sec){tree[now].l, tree[now].r, val};
return ;
}
int mid = (tree[now].l + tree[now].r) >> 1;
if(pos <= mid) update(lson, pos, val);
else update(rson, pos, val);
push_up(tree[now], tree[lson], tree[rson]);
}
node query(int now, int l, int r){
if(tree[now].l >= l && tree[now].r <= r){
return tree[now];
}
int mid = (tree[now].l + tree[now].r) >> 1;
if(r <= mid) return query(lson, l, r);
else if(l > mid) return query(rson, l, r);
else{
node ls = query(lson, l, mid), rs = query(rson, mid + 1, r), res;
res.l = l; res.r = r;
push_up(res, ls, rs);
return res;
}
}
int main(){
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
build(1, 1, n);
// int cnt = 0;
for(int i = 1; i <= q; i++){
int op, x, y;
scanf("%d%d%d",&op,&x,&y);
if(op == 1) update(1, x, y);
else{
ll res = max(query(1, x, y).max_res.mul, 1ll);
if(res >= INF) printf("Too large\n");
else printf("%lld\n",res);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Apifox不支持离线,Apipost可以!
· 历时 8 年,我冲上开源榜前 8 了!
· 零经验选手,Compose 一天开发一款小游戏!
· Trae 开发工具与使用技巧
· 通过 API 将Deepseek响应流式内容输出到前端