费用流+线段树

看见这个题我们马上就能想到费用流,设立源汇,分别向每个点连接容量为1费用为0的边,然后相邻的点之间连边,费用为点权,跑费用流就行了,但是很明显这样会超时,那么我们要优化一下,我们观察费用流的过程,发现对于点与点之间的边,每次取一段区间相当于把正向边改为反向边,费用变负,于是我们可以用线段树来模拟这个过程,像费用流一样贪心地选取区间的最大子段和,然后取反,每次取k次,然后恢复。这样就好了

但是写的时候有很多问题,比如如何返回一个区间?结构体!参考了popoqqq大神的代码,发现我们可以通过重载小于号直接对结构体取max,这样就十分好写了

然后这道题有点卡常,一定要在重载的时候把传入参数变成const+引用,这样在cf上快了200ms

这就是传说中的五倍经验吗

#include<bits/stdc++.h>
using namespace std;
const int N = ;
namespace IO
{
const int Maxlen = N * ;
char buf[Maxlen], *C = buf;
int Len;
inline void read_in()
{
Len = fread(C, , Maxlen, stdin);
buf[Len] = '\0';
}
inline void fread(int &x)
{
x = ;
int f = ;
while (*C < '' || '' < *C) { if(*C == '-') f = -; ++C; }
while ('' <= *C && *C <= '') x = (x << ) + (x << ) + *C - '', ++C;
x *= f;
}
inline void read(int &x)
{
x = ;
int f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << ) + (x << ) + c - ''; c = getchar(); }
x *= f;
}
inline void read(long long &x)
{
x = ;
long long f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << 1ll) + (x << 3ll) + c - ''; c = getchar(); }
x *= f;
}
} using namespace IO;
struct data {
int l, r, v;
data() {}
data(int l, int r, int v) : l(l), r(r), v(v) {}
friend bool operator < (const data &a, const data &b) { return a.v < b.v; }
friend data operator + (const data &a, const data &b) { return data(a.l, b.r, a.v + b.v); }
};
struct node {
data lmax, rmax, mx, mn, lmin, rmin, sum;
int tag;
node() {}
node(int x, int v) {
lmax = rmax = mx = mn = lmin = rmin = sum = data(x, x, v);
}
friend node operator + (const node &a, const node &b) {
node c;
if(a.tag == -) return b;
if(b.tag == -) return a;
c.tag = ;
c.sum = a.sum + b.sum;
c.lmax = max(a.lmax, a.sum + b.lmax);
c.lmin = min(a.lmin, a.sum + b.lmin);
c.rmax = max(b.rmax, a.rmax + b.sum);
c.rmin = min(b.rmin, a.rmin + b.sum);
c.mx = max(max(a.mx, b.mx), a.rmax + b.lmax);
c.mn = min(min(a.mn, b.mn), a.rmin + b.lmin);
return c;
}
} tree[N << ], st[];
int n, q;
int a[N];
void paint(node &o)
{
swap(o.lmax, o.lmin);
swap(o.rmax, o.rmin);
swap(o.mx, o.mn);
o.sum.v *= -;
o.lmax.v *= -;
o.lmin.v *= -;
o.rmax.v *= -;
o.rmin.v *= -;
o.mx.v *= -;
o.mn.v *= -;
o.tag ^= ;
}
void pushdown(int x)
{
if(tree[x].tag <= ) return;
paint(tree[x << ]);
paint(tree[x << | ]);
tree[x].tag ^= ;
}
void build(int l, int r, int x)
{
if(l == r)
{
tree[x] = node(l, a[l]);
return;
}
int mid = (l + r) >> ;
build(l, mid, x << );
build(mid + , r, x << | );
tree[x] = tree[x << ] + tree[x << | ];
}
node query(int l, int r, int x, int a, int b)
{
if(l > b || r < a) return tree[];
if(l >= a && r <= b) return tree[x];
pushdown(x);
int mid = (l + r) >> ;
return (query(l, mid, x << , a, b)) + (query(mid + , r, x << | , a, b));
}
void reverse(int l, int r, int x, int a, int b)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
paint(tree[x]);
return;
}
pushdown(x);
int mid = (l + r) >> ;
reverse(l, mid, x << , a, b);
reverse(mid + , r, x << | , a, b);
tree[x] = tree[x << ] + tree[x << | ];
}
void update(int l, int r, int x, int pos, int v)
{
if(l == r)
{
tree[x] = node(l, v);
return;
}
pushdown(x);
int mid = (l + r) >> ;
if(pos <= mid) update(l, mid, x << , pos, v);
else update(mid + , r, x << | , pos, v);
tree[x] = tree[x << ] + tree[x << | ];
}
int main()
{
read_in();
fread(n);
for(int i = ; i <= n; ++i) fread(a[i]);
tree[].tag = -;
build(, n, );
fread(q);
while(q--)
{
int opt, l, r, v;
fread(opt);
if(opt == )
{
fread(l);
fread(v);
update(, n, , l, v);
}
if(opt == )
{
fread(l);
fread(r);
fread(v);
int sum = , top = ;
while(v--)
{
node ans = query(, n, , l, r);
if(ans.mx.v <= ) break;
reverse(, n, , ans.mx.l, ans.mx.r);
node tmp = query(, n, , ans.mx.l, ans.mx.r);
st[++top] = ans;
sum += ans.mx.v;
}
printf("%d\n", sum);
for(int i = top; i; --i) reverse(, n, , st[i].mx.l, st[i].mx.r);
}
}
return ;
}

bzoj3638的更多相关文章

  1. 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)

    [BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...

  2. 【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 ...

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

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

  4. [BZOJ3638 && BZOJ3272]带修区间不相交最大K子段和(线段树模拟费用流)

    https://www.cnblogs.com/DaD3zZ-Beyonder/p/5634149.html k可重区间集问题有两种建图方式,可能这一种才可以被线段树优化. 换个角度看,这也是一个类似 ...

  5. BZOJ3638|CodeForces 280D k-Maximum Subsequence Sum

    题目链接:戳我 一类典型模型.线段树模拟网络流+区间最大K段和. 因为不会写,所以参考了黄学长的博客.但是我觉得他说得不够详细,所以想好好地解释一下: 前置技能1:区间最大子段和 如果K=1的时候怎么 ...

  6. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

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

  7. bzoj3638 Cf172 k-Maximum Subsequence Sum

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3638 [题解] 看到k<=20就感觉很py了啊 我们用一棵线段树维护选段的过程,能选到 ...

  8. [转载]hzwer的bzoj题单

    counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...

  9. BZOJ刷题列表【转载于hzwer】

    沿着黄学长的步伐~~ 红色为已刷,黑色为未刷,看我多久能搞完吧... Update on 7.26 :之前咕了好久...(足见博主的flag是多么emmm......)这几天开始会抽时间刷的,每天几道 ...

随机推荐

  1. 获得HttpServletRequest 和HttpSession对象

    package org.jeecgframework.core.util; import java.util.HashMap; import java.util.Map; import javax.s ...

  2. centos下wget时提示unable to resolve host address ...

    网络正常的情况,可以查看/etc/resolv.conf [root@localhost ~]# more /etc/resolv.conf # Generated by NetworkManager ...

  3. CPU问题定位与解决

    CPU问题定位基本流程:   性能计数器诊断 主要用到的性能计数器 %Process Time 全实例 (主要用于查看当前服务器的CPU 情况) %Process Time sqlservr (主要用 ...

  4. Javascript 检查字符串是否是数字的几种方法

    //判断是否是正整数 function IsNum(s) { if(s!=null){ var r,re; re = /\d*/i; //\d表示数字,*表示匹配多个数字 r = s.match(re ...

  5. msp430项目编程02

    msp430中项目---液晶1602显示 1.液晶1602工作原理 2.电路原理说明 3.代码(静态显示) 4.代码(动态显示) 5.项目总结 msp430项目编程 msp430入门学习

  6. vagrant的学习 之 ThinkPHP3.2

    vagrant的学习 之 ThinkPHP3.2 (1)在web目录下新建tp32目录: cd /home/www/ mkdir tp32 (2)下载框架 我从ThinkPHP官网下载了ThinkPH ...

  7. foobar2000 iOS使用,并连接PC的歌曲进行播放

    foobar2000移动版下载地址:http://mobile.foobar2000.com/ 要实现歌曲互通有两种方法,使用iOS客户端的FTP Server用PC上传歌曲到iOS手机,和在PC上使 ...

  8. 在SUSE12中使用 Machinery 进行高级系统管理

    简单介绍 在 SUSE Linux Enterprise 12 中.SUSE 如今推出了面向系统管理员的 Machinery.作为其高级系统管理模块的一部分.Machinery 是适用于 Linux ...

  9. Android调试工具_ Stetho

    Stetho是Facebook开源的一个Android平台调试工具. Stetho能实如今不root手机的情况下,通过Chrome查看App的布局,Sqlite,SharedPreference.Ne ...

  10. yii2利用自带UploadedFile上传图片

    创建一个 models/UploadForm.php: <?php namespace app\models; use yii\base\Model; use yii\web\UploadedF ...