直接维护选k个子段时的最优解似乎也可以做,然而复杂度是O(nk2logn),显然跑不过。

  考虑一种费用流做法。序列里每个点拆成入点和出点,源连入汇连出,入点和出点间连流量1费用ai的边,相邻点出点向入点连流量1费用0的边,整体限流k。

  直接跑当然还不如暴力。观察一下这个做法是在干啥:每次选择费用最大的一段,然后利用反向边将这一段的费用取反。

  这个做法看起来非常贪心(不过费用流本质上也挺贪心的),不过看起来确实是对的。当然从贪心角度就完全不会证了。

  于是考虑利用这种做法维护。那么线段树维护区间最大子段和和最小子段和,取反时交换,剩下的是基本操作了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
int n,m,a[N];
struct data{int L,R,max,maxl,maxr,min,minl,minr,sum,rmax,rmaxid,rmin,rminid,lmax,lmaxid,lmin,lminid,rev;
}tree[N<<],q[];
data merge(data a,data b)
{
data u;
u.rev=;u.L=a.L,u.R=b.R;
u.sum=a.sum+b.sum;
if (a.lmax>a.sum+b.lmax) u.lmax=a.lmax,u.lmaxid=a.lmaxid;
else u.lmax=a.sum+b.lmax,u.lmaxid=b.lmaxid;
if (a.lmin<a.sum+b.lmin) u.lmin=a.lmin,u.lminid=a.lminid;
else u.lmin=a.sum+b.lmin,u.lminid=b.lminid;
if (b.rmax>b.sum+a.rmax) u.rmax=b.rmax,u.rmaxid=b.rmaxid;
else u.rmax=b.sum+a.rmax,u.rmaxid=a.rmaxid;
if (b.rmin<b.sum+a.rmin) u.rmin=b.rmin,u.rminid=b.rminid;
else u.rmin=b.sum+a.rmin,u.rminid=a.rminid;
u.max=a.rmax+b.lmax;u.maxl=a.rmaxid;u.maxr=b.lmaxid;
u.min=a.rmin+b.lmin;u.minl=a.rminid;u.minr=b.lminid;
if (a.max>u.max) u.max=a.max,u.maxl=a.maxl,u.maxr=a.maxr;
if (a.min<u.min) u.min=a.min,u.minl=a.minl,u.minr=a.minr;
if (b.max>u.max) u.max=b.max,u.maxl=b.maxl,u.maxr=b.maxr;
if (b.min<u.min) u.min=b.min,u.minl=b.minl,u.minr=b.minr;
return u;
}
void work(int k)
{
tree[k].rev^=;
tree[k].sum=-tree[k].sum;
swap(tree[k].max,tree[k].min);tree[k].max=-tree[k].max,tree[k].min=-tree[k].min;
swap(tree[k].maxl,tree[k].minl);swap(tree[k].maxr,tree[k].minr);
swap(tree[k].lmax,tree[k].lmin);tree[k].lmax=-tree[k].lmax,tree[k].lmin=-tree[k].lmin;
swap(tree[k].lmaxid,tree[k].lminid);
swap(tree[k].rmax,tree[k].rmin);tree[k].rmax=-tree[k].rmax,tree[k].rmin=-tree[k].rmin;
swap(tree[k].rmaxid,tree[k].rminid);
}
void down(int k){work(k<<),work(k<<|),tree[k].rev=;}
void build(int k,int l,int r)
{
tree[k].L=l,tree[k].R=r;
if (l==r)
{
tree[k].sum=tree[k].max=tree[k].min=tree[k].rmax=tree[k].rmin=tree[k].lmax=tree[k].lmin=a[l];
tree[k].maxl=tree[k].maxr=tree[k].minl=tree[k].minr=tree[k].rmaxid=tree[k].rminid=tree[k].lmaxid=tree[k].lminid=l;
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
tree[k]=merge(tree[k<<],tree[k<<|]);
}
void rev(int k,int l,int r)
{
if (tree[k].L==l&&tree[k].R==r) {work(k);return;}
if (tree[k].rev) down(k);
int mid=tree[k].L+tree[k].R>>;
if (r<=mid) rev(k<<,l,r);
else if (l>mid) rev(k<<|,l,r);
else rev(k<<,l,mid),rev(k<<|,mid+,r);
tree[k]=merge(tree[k<<],tree[k<<|]);
}
void modify(int k,int p,int x)
{
if (tree[k].L==tree[k].R)
{
tree[k].sum=tree[k].max=tree[k].min=tree[k].rmax=tree[k].rmin=tree[k].lmax=tree[k].lmin=x;
tree[k].rev=;
return;
}
if (tree[k].rev) down(k);
int mid=tree[k].L+tree[k].R>>;
if (p<=mid) modify(k<<,p,x);
else modify(k<<|,p,x);
tree[k]=merge(tree[k<<],tree[k<<|]);
}
data query(int k,int l,int r)
{
if (tree[k].L==l&&tree[k].R==r) return tree[k];
if (tree[k].rev) down(k);
int mid=tree[k].L+tree[k].R>>;
if (r<=mid) return query(k<<,l,r);
else if (l>mid) return query(k<<|,l,r);
else return merge(query(k<<,l,mid),query(k<<|,mid+,r));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3272.in","r",stdin);
freopen("bzoj3272.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) a[i]=read();
m=read();
build(,,n);
while (m--)
{
int op=read();
if (op)
{
int l=read(),r=read(),k=read(),ans=;
for (int i=;i<=k;i++)
{
q[i]=query(,l,r);
if (q[i].max>) ans+=q[i].max,rev(,q[i].maxl,q[i].maxr);
else {k=i-;break;}
}
for (int i=;i<=k;i++)
rev(,q[i].maxl,q[i].maxr);
printf("%d\n",ans);
}
else
{
int x=read(),y=read();
modify(,x,y);
}
}
return ;
}

BZOJ3267/3272 KC采花/Zgg吃东西(线段树)的更多相关文章

  1. BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  2. bzoj3272 Zgg吃东西

    题目描述: bz 题解: 线段树模拟费用流. 想法和种树有点类似. 每次取区间内权值和最大的一段,然后整体乘$-1$,代表再次选中时会去掉之前的影响. 线段树维护一堆东西…… 小白逛公园双倍快乐.乘$ ...

  3. bzoj3272: Zgg吃东西&&3267: KC采花

    口胡 我们容易得到一个费用流的做法,流出k的流量分配给各个点,各个点向下一个点流费用为它的价值的边,然后汇总到ed 观察发现对于流一次,相当于选择了一个区间 如果流了反向边,相当于减去了这一段 可以用 ...

  4. bzoj 3267: KC采花&&3272&&3638&&3502 线段树

    题目大意 给定一个长为n的序列,维护两种操作: 1.单点修改 2.在[l,r]这段区间中取k个互不相交的子段,使子段之和最大. \(n \leq 50000,k \leq 20\) 题解 四倍经验.( ...

  5. 【BZOJ-3638&3272&3267&3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广

    3638: Cf172 k-Maximum Subsequence Sum Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 174  Solved: 9 ...

  6. BZOJ 2743 【HEOI2012】 采花

    题目链接:采花 这道题一眼看去,一个很显然的想法就是莫队.但是数据范围是\(10^6\)级别的,莫队显然已经过不去了. 其实感觉这道题和以前写过的一道题HH的项链很像.只不过那道题要求的是区间出现次数 ...

  7. 【HEOI2012】采花 BZOJ2743

    Description 萧芸斓是Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一 ...

  8. 采花 bzoj 2743

    采花(1s 128MB)flower [题目描述] 萧芸斓是Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了n朵花,花有c种颜色(用整 ...

  9. BZOJ 2743: [HEOI2012]采花

    2743: [HEOI2012]采花 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 2056  Solved: 1059[Submit][Status ...

随机推荐

  1. C++模板的实现(模板函数和模板类,附带模板实现顺序表和链表代码)

    文章链接:https://blog.csdn.net/qq_38646470/article/details/80209469

  2. 树莓派UPS-18650,添加时钟

    1.简介 UPS-18650 是一个专门为树莓派(以下简称 pi)所设计的 UPS 电源,采用两颗标准 的 18650 锂电池进行供电,支持外部电源插入检测,支持边充边放,既插上外部电源时, pi 由 ...

  3. 微信小程序日记(一)

    一.基础知识(目录与配置) (1)标签 小程序的view相当于HTML的div标签一样,作占位 (2)每一个页面都需要在app.json里面注册,例如: { { "pages": ...

  4. 详解YUV420数据格式

    原文地址:http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html 1. YUV简介 YUV定义:分为三个分量,“Y”表示明亮度( ...

  5. python容器类型的协议

    1.协议(Protocols)与其他编程语言中的接口恒相似,它规定你哪些地方必须要定义,然而在python中的协议就显得不那么正式,事实上,在python中,协议更像是一种指南. 2.序列类型和映射类 ...

  6. c语言数字图像处理(十):阈值处理

    定义 全局阈值处理 假设某一副灰度图有如下的直方图,该图像由暗色背景下的较亮物体组成,从背景中提取这一物体时,将阈值T作为分割点,分割后的图像g(x, y)由下述公式给出,称为全局阈值处理 多阈值处理 ...

  7. python快速入门——进入数据挖掘你该有的基础知识

    这篇文章是用来总结python中重要的语法,通过这些了解你可以快速了解一段python代码的含义 Python 的基础语法来带你快速入门 Python 语言.如果你想对 Python 有全面的了解请关 ...

  8. awk之close函数

    echo "21 2 " | awk '{ first[NR]=$ second[NR]=$ }END{ print "======打印第1列并排序:========== ...

  9. 机器学习算法 --- SVM (Support Vector Machine)

    一.SVM的简介 SVM(Support Vector Machine,中文名:支持向量机),是一种非常常用的机器学习分类算法,也是在传统机器学习(在以神经网络为主的深度学习出现以前)中一种非常牛X的 ...

  10. DockerCon2017前瞻 - Docker企业版体验

    DockerCon 2017将于四月17号在美国Austin召开.在去年DockerCon上,Docker公司一系列的发布吹响了进军企业市场的号角.今天,容器技术已经愈发成熟,被越来越多的企业所关注和 ...