BZOJ3638|CodeForces 280D k-Maximum Subsequence Sum
题目链接:戳我
一类典型模型。线段树模拟网络流+区间最大K段和。
因为不会写,所以参考了黄学长的博客。但是我觉得他说得不够详细,所以想好好地解释一下:
前置技能1:区间最大子段和
如果K=1的时候怎么办?大家可以去参考一下蒟蒻的这篇博客:戳我
前置技能2:最长K可重区间集问题
求最长K可重区间集的最大长度。这个是网络流能解决的问题,具体建模请看蒟蒻的这篇博客:戳我
但是我们发现如果用网络流来做的话,显然这道题的数据范围太大了,对于复杂度上届为\(O(n^2m)\)的网络流,不光说仅仅点数就有1e5个,我们连边的话级别也是n*(n-1)/2的。然后我们考虑一下网络流到底是怎么运作的?我们求的是最大费用流,显然不断地增广过程就是不断地在寻找费用最大的区间然后累加到答案里面。但是因为可重叠的最大量为1,所以有时候考虑到更换更优解,我们需要把流量费用退回去,也就把它变成负的。这个过程我们可以用线段树来模拟——
增广的过程我们可以用寻找最大子段和来替代。然后推流可以用线段树区间反转来做。(区间反转如果不会的话。。。或许可以看看luogu的文艺平衡树???)
然后时间复杂度就十分优秀地化简到了\(O(mklogn)\),对于四秒+很快的cf机子应该还是绰绰有余了。
备注一下代码里面的变量意义:
mx:当前值
mn:mx的相反数
嵌套——
maxs:区间最大子段和
sum:区间和(为什么要记录这个我就不说了,大家参考前置技能1)
lx:区间最大前缀子段和
rx:区间最大后缀子段和
p1:区间最大子段和的左区间
p2:区间最大子段和的右区间
因为我们合并的时候有三种情况,其中一种是有可能跨左右区间,所以我们还需要记录lp:区间最大前缀子段和的右端点,rp:区间最大后缀子段和的前端点。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
#define MAXN 100010
inline int read()
{
int f=1,x=0; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
return x*f;
}
int n,m;
int a[MAXN];
struct Node{int lp,rp,lx,rx,sum,maxs,p1,p2;};
struct Node2{int flag,tag;Node mx,mn;}node[MAXN<<2];
vector<pair<int,int> >cur;
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline Node merge(Node x,Node y)
{
Node t;
t.sum=x.sum+y.sum;
if(x.sum+y.lx>x.lx) t.lx=x.sum+y.lx,t.lp=y.lp;
else t.lx=x.lx,t.lp=x.lp;
if(x.rx+y.sum>y.rx) t.rx=x.rx+y.sum,t.rp=x.rp;
else t.rx=y.rx,t.rp=y.rp;
t.maxs=x.maxs,t.p1=x.p1,t.p2=x.p2;
if(y.maxs>t.maxs) t.maxs=y.maxs,t.p1=y.p1,t.p2=y.p2;
if(x.rx+y.lx>t.maxs) t.maxs=x.rx+y.lx,t.p1=x.rp,t.p2=y.lp;
return t;
}
inline void push_up(int x)
{
node[x].mn=merge(node[ls(x)].mn,node[rs(x)].mn);
node[x].mx=merge(node[ls(x)].mx,node[rs(x)].mx);
}
inline void init(Node &x,int pos,int k)
{
x.p1=x.p2=x.lp=x.rp=pos;
x.lx=x.rx=x.maxs=x.sum=k;
}
inline void build(int x,int l,int r)
{
if(l==r)
{
init(node[x].mn,l,-a[l]);
init(node[x].mx,l,a[l]);
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
push_up(x);
}
inline void push_down(int x,int l,int r)
{
if(node[x].tag)
{
swap(node[ls(x)].mn,node[ls(x)].mx);
swap(node[rs(x)].mn,node[rs(x)].mx);
node[ls(x)].tag^=1,node[rs(x)].tag^=1,node[x].tag^=1;
}
}
inline void reverse(int x,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr)
{swap(node[x].mn,node[x].mx);node[x].tag^=1;return;}
push_down(x,l,r);
int mid=(l+r)>>1;
if(rr<=mid) reverse(ls(x),l,mid,ll,rr);
else if(mid<ll) reverse(rs(x),mid+1,r,ll,rr);
else reverse(ls(x),l,mid,ll,mid),reverse(rs(x),mid+1,r,mid+1,rr);
push_up(x);
}
inline void update(int x,int l,int r,int pos,int k)
{
if(l==r)
{init(node[x].mx,l,k);init(node[x].mn,l,-k);return;}
int mid=(l+r)>>1;
push_down(x,l,r);
if(pos<=mid) update(ls(x),l,mid,pos,k);
else update(rs(x),mid+1,r,pos,k);
push_up(x);
}
inline Node query(int x,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr) return node[x].mx;
push_down(x,l,r);
int mid=(l+r)>>1;
if(rr<=mid) return query(ls(x),l,mid,ll,rr);
else if(mid<ll) return query(rs(x),mid+1,r,ll,rr);
else return merge(query(ls(x),l,mid,ll,mid),query(rs(x),mid+1,r,mid+1,rr));
}
inline void solve(int x,int l,int r,int k)
{
int cur_ans=0;
cur.clear();
for(int i=1;i<=k;i++)
{
Node t=query(1,1,n,l,r);
if(t.maxs>0) cur_ans+=t.maxs;
else break;
reverse(1,1,n,t.p1,t.p2);
cur.push_back(make_pair(t.p1,t.p2));
}
for(int i=cur.size()-1;i>=0;i--)
reverse(1,1,n,cur[i].first,cur[i].second);
printf("%d\n",cur_ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
n=read();
for(int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
m=read();
while(m--)
{
int op=read();
if(op==1)
{
int u=read(),v=read(),k=read();
solve(1,u,v,k);
}
else
{
int pos=read(),k=read();
update(1,1,n,pos,k);
}
}
return 0;
}
BZOJ3638|CodeForces 280D k-Maximum Subsequence Sum的更多相关文章
- 中国大学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 ...
- PTA (Advanced Level) 1007 Maximum Subsequence Sum
Maximum Subsequence Sum Given a sequence of K integers { N1, N2, ..., NK }. A continuous su ...
- 【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 ...
- PAT 甲级 1007 Maximum Subsequence Sum (25)(25 分)(0不是负数,水题)
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- PAT 1007 Maximum Subsequence Sum(最长子段和)
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- pat1007. Maximum Subsequence Sum (25)
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- PTA 01-复杂度2 Maximum Subsequence Sum (25分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/663 5-1 Maximum Subsequence Sum (25分) Given ...
随机推荐
- 【LUA table 移除操作非常慢】
LUA的表有插入和删除两种操作.插入操作非常快,100000次操作都在0.01S左右,而删除操作在表元素大于10000时却急速变慢,测试如下: t = {} local t1= os.clock() ...
- 【原】Coursera—Andrew Ng机器学习—Week 9 习题—异常检测
[1]异常检测 [2]高斯分布 [3]高斯分布 [4] 异常检测 [5]特征选择 [6] [7]多变量高斯分布 Answer: ACD B 错误.需要矩阵Σ可逆,则要求m>n 测验1 Answ ...
- SPI子系统分析之一:框架
内核版本:3.9.5 SPI子系统概述: 一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号. SPI总线上有两类设备: 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式M ...
- GC类
[GC类] GC是一个静态类. 垃圾回收器跟踪并回收托管内存中分配的对象.垃圾回收器定期执行垃圾回收以回收分配给没有有效引用的对象的内存.当使用可用内存不能满足内存请求时,垃圾回收会自动进行.或者,应 ...
- 【HDU - 5442】Favorite Donut 【最大表示法+KMP/后缀数组】
题意 给出一个长度为n的环状由小写字母组成的序列,请找出从何处断开,顺时针还是逆时针,使得字典序最大.如果两个字符串的字典序一样大,那么它会选择下下标最小的那个.如果某个点顺时针逆时针产生的字典序大小 ...
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
1 Background ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的 ...
- Python操作SQLServer示例
本文主要是Python操作SQLServer示例,包括执行查询及更新操作(写入中文). 需要注意的是:读取数据的时候需要decode('utf-8'),写数据的时候需要encode('utf-8'), ...
- MYSQl修改临时文件目录
MSYQL在执行查询语句时报出以下错误: ERROR 3(HY000):Error writing file 'tmp/MY1yjZEI'(Errcode:28) 看了下/tmp所在目录的磁盘情况,发 ...
- zigbee组播通信原理
组播: 在zigbee网络里面,把网络节点标记为组的方式来进行通信:发送模块如果发送的组号和网络里标记模块的组号相对应,那么这些模块就可以拿到这些无线数据包. 特点: 1.分组中组的编号有两个字节. ...
- jQuary总结3: jQuery语法1
1.jQuery样式操作 1.1 设置或者修改样式,操作的是style属性. 单样式语法: jQuery对象.css('属性名', '属性值') //html <div id="box ...