【CF280D】k-Maximum Subsequence Sum(大码量多细节线段树)
大致题意: 给你一个序列,让你支持单点修改以及询问给定区间内选出至多\(k\)个不相交子区间和的最大值。
题意转换
这道题看似很不可做,实际上可以通过一个简单转换让其变可做。
考虑每次选出一个区间,统计答案后将这个区间内所有数乘上\(-1\),再继续求答案,这样做是显然合法的。
于是就变成了在给定区间内选出权值和最大子区间和区间乘\(-1\)两种操作。
具体实现
具体实现十分复杂。。。
对于线段树的每个节点,我们需要维护区间和、最大值及其区间、前缀最大值及其区间、后缀最大值及其区间。
但由于要乘\(-1\),因此我们同时还要维护最小值及其区间、前缀最小值及其区间、后缀最小值及其区间,这样乘\(-1\)后只要交换最大值和最小值即可方便地维护信息。
口胡起来很简洁,但这么多信息实现起来就需要点技巧了。
对于我写的class套struct套struct套struct实在不想多说。。。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define K 20
#define max(x,y) ((x)<(y)?(y):(x))
#define Gmax(x,y) (x<(y)&&(x=(y),0))
using namespace std;
int n,a[N+5];struct Op {int l,r;I Op(CI x=0,CI y=0):l(x),r(y){}}s[K+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int f,T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0,f=1;W(!D) f=c^'-'?1:-1;W(x=tn+(c&15),D);x*=f;}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
struct data//记录某个权值及其区间
{
int l,r,v;I data(CI x=0,CI y=0,CI z=0):l(x),r(y),v(z){}
I data operator + (Con data& o) Con {return data(l,o.r,v+o.v);}
I bool operator < (Con data& o) Con {return v<o.v;}
I void operator *= (CI o) {v*=o;}
};
struct status//记录一个区间最值、前缀最值、后缀最值
{
data Pre,Nxt,Val;I status() {Pre=Nxt=Val=data();}
I void operator *= (CI o) {Pre*=o,Nxt*=o,Val*=o;}
I data operator = (Con data& o) {return Pre=Nxt=Val=o;}
};
struct qdata//由于询问时需要用到区间和,所以将一个status(最值信息)和一个data(和)绑一起
{
status Max;data Sum;
I qdata(Con status& x=status(),Con data& y=data()):Max(x),Sum(y){}
};
class SegmentTree//线段树
{
private:
#define P CI l=1,CI r=n,CI rt=1
#define L l,mid,rt<<1
#define R mid+1,r,rt<<1|1
#define LS(x) O[x<<1]
#define RS(x) O[x<<1|1]
#define PU(x)\
(\
O[x].Max.Pre=max(LS(x).Max.Pre,LS(x).Sum+RS(x).Max.Pre),\
O[x].Max.Nxt=max(RS(x).Max.Nxt,LS(x).Max.Nxt+RS(x).Sum),\
O[x].Max.Val=max(LS(x).Max.Nxt+RS(x).Max.Pre,max(LS(x).Max.Val,RS(x).Max.Val)),\
O[x].Min.Pre=min(LS(x).Min.Pre,LS(x).Sum+RS(x).Min.Pre),\
O[x].Min.Nxt=min(RS(x).Min.Nxt,LS(x).Min.Nxt+RS(x).Sum),\
O[x].Min.Val=min(LS(x).Min.Nxt+RS(x).Min.Pre,min(LS(x).Min.Val,RS(x).Min.Val)),\
O[x].Sum=LS(x).Sum+RS(x).Sum\
)//上传信息,应该可以再套用define更简短地实现,但我不会。。。
#define PD(x) !~O[x].F&&(Upt(x<<1),Upt(x<<1|1),O[x].F=1)//下传乘-1的标记
#define Assign(x,v) (O[x].Sum=O[x].Max=O[x].Min=data(l,r,v))//赋值
#define Upt(x) (O[x].Sum*=-1,O[x].Max*=-1,O[x].Min*=-1,swap(O[x].Max,O[x].Min),O[x].F*=-1)//乘-1,交换最值
struct Il {data Sum;status Max,Min;int F;I Il() {Sum=data(),Max=Min=status(),F=1;}}O[N<<2];//维护线段树上节点信息
public:
I void Build(P) {if(l==r) return (void)Assign(rt,a[l]);RI mid=l+r>>1;Build(L),Build(R),PU(rt);}//初始化建树
I void Update(CI x,CI v,P)//单点修改
{
if(l==r) return (void)Assign(rt,v);PD(rt);RI mid=l+r>>1;
x<=mid?Update(x,v,L):Update(x,v,R),PU(rt);
}
I void Modify(CI tl,CI tr,P)//区间乘-1
{
if(tl<=l&&r<=tr) return (void)Upt(rt);PD(rt);RI mid=l+r>>1;
tl<=mid&&(Modify(tl,tr,L),0),tr>mid&&(Modify(tl,tr,R),0),PU(rt);
}
I qdata Query(CI tl,CI tr,P)//询问
{
if(tl<=l&&r<=tr) return qdata(O[rt].Max,O[rt].Sum);PD(rt);RI mid=l+r>>1;
if(tr<=mid) return Query(tl,tr,L);if(tl>mid) return Query(tl,tr,R);
qdata ql=Query(tl,tr,L),qr=Query(tl,tr,R),res;//合并左、右子树答案
res.Max.Pre=max(ql.Max.Pre,ql.Sum+qr.Max.Pre),
res.Max.Nxt=max(qr.Max.Nxt,ql.Max.Nxt+qr.Sum),
res.Max.Val=max(ql.Max.Nxt+qr.Max.Pre,max(ql.Max.Val,qr.Max.Val));
return res.Sum=ql.Sum+qr.Sum,res;
}
}S;
int main()
{
RI Qtot,i,op,x,y,z,ans,cnt;data t;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);
S.Build(),F.read(Qtot);W(Qtot--)
{
if(F.read(op,x,y),op)//处理询问
{
F.read(z),ans=cnt=0;W(z--)
{
if((t=S.Query(x,y).Max.Val).v>0) S.Modify(t.l,t.r),s[++cnt]=Op(t.l,t.r),ans+=t.v;//求答案,乘-1
else break;//如果小于0就退出
}
W(cnt) S.Modify(s[cnt].l,s[cnt].r),--cnt;F.writeln(ans);//撤销乘-1,输出答案
}else S.Update(x,y);//单点修改
}return F.clear(),0;
}
【CF280D】k-Maximum Subsequence Sum(大码量多细节线段树)的更多相关文章
- Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]
洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...
- BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=3836 (Codeforces) http://codeforces.com ...
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
- PTA (Advanced Level) 1007 Maximum Subsequence Sum
Maximum Subsequence Sum Given a sequence of K integers { N1, N2, ..., NK }. A continuous su ...
- 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 01-复杂度2 Maximum Subsequence Sum (25分)
01-复杂度2 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1,N2, ..., NK }. ...
- PAT1007:Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- 【DP-最大子串和】PAT1007. Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- PAT Maximum Subsequence Sum[最大子序列和,简单dp]
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- PAT甲 1007. Maximum Subsequence Sum (25) 2016-09-09 22:56 41人阅读 评论(0) 收藏
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
随机推荐
- 使用 Hbuilder 连接手机调试移动端项目
点击界面上的浏览器右侧的倒三角. 弹出列表以后,点击最后一行 “设置web服务器...”.继续弹出,点击右下角的“外置Web服务器设置”. 点新建. 弹出框后,填入“名称”和“浏览器运行U ...
- 【CodeChef】December Challenge 2019 Div1 解题报告
点此进入比赛 这次比赛本来想好好打的,但不幸的是,这周先是要认真复习准备月考,考完又是发烧在床上躺了一个周末,所以最终没能打完. 我还是好弱啊. \(T1\):Binary XOR(点此看题面) 大致 ...
- 融云技术分享:解密融云IM产品的聊天消息ID生成策略
本文来自融云技术团队原创分享,原文发布于“融云全球互联网通信云”公众号,原题<如何实现分布式场景下唯一 ID 生成?>,即时通讯网收录时有部分改动. 1.引言 对于IM应用来说,消息ID( ...
- IT兄弟连 Java语法教程 数组 使用foreach循环遍历数组元素
从JDK5之后,Java提供了一种更简单的循环:foreach循环,也叫作增强for循环,这种循环遍历数组和集合更加简洁.使用foreach循环遍历数组和集合元素时,无需获得数组或集合的长度,无需根据 ...
- javascript检索某个字符或字符串在源字符串中的位置(下标)
indexOf()方法 JavaScript中的String对象提供了一个indexOf(searchValue, fromIndex)方法用于检索某个字符或字符串在源字符串中第一次出现的位置(下标) ...
- angular 前端路由不生效解决方案
angular 前端路由不生效解决方案 Intro 最近使用 Angular 为我的活动室预约项目开发一个前后端分离的客户端,在部署上遇到了一个问题,前端路由不生效,这里记录一下.本地开发正常,但是部 ...
- GO 函数的参数
一.函数 函数的参数 1.1 参数的使用 形式参数:定义函数时,用于接收外部传入的数据,叫做形式参数,简称形参. 实际参数:调用函数时,传给形参的实际的数据,叫做实际参数,简称实参. 函数调用: ...
- 用Python在Excel里画出蒙娜丽莎
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 麦麦麦造 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- File文件的创建,删除 createNewFile() delete()
package seday03; import java.io.File;import java.io.IOException; /*** 使用File新建一个test1.txt文件* @author ...
- Java生鲜电商平台-商品基础业务架构设计-商品设计
Java生鲜电商平台-商品基础业务架构设计-商品设计 在生鲜电商的商品中心,在电子商务公司一般是后台管理商品的地方.在前端而言,是商家为了展示商品信息给用户的地方,它是承担了商品的数据,订单,营销活动 ...