bzoj3638
费用流+线段树
看见这个题我们马上就能想到费用流,设立源汇,分别向每个点连接容量为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的更多相关文章
- 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)
[BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...
- 【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 ...
- BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- [BZOJ3638 && BZOJ3272]带修区间不相交最大K子段和(线段树模拟费用流)
https://www.cnblogs.com/DaD3zZ-Beyonder/p/5634149.html k可重区间集问题有两种建图方式,可能这一种才可以被线段树优化. 换个角度看,这也是一个类似 ...
- BZOJ3638|CodeForces 280D k-Maximum Subsequence Sum
题目链接:戳我 一类典型模型.线段树模拟网络流+区间最大K段和. 因为不会写,所以参考了黄学长的博客.但是我觉得他说得不够详细,所以想好好地解释一下: 前置技能1:区间最大子段和 如果K=1的时候怎么 ...
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- bzoj3638 Cf172 k-Maximum Subsequence Sum
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3638 [题解] 看到k<=20就感觉很py了啊 我们用一棵线段树维护选段的过程,能选到 ...
- [转载]hzwer的bzoj题单
counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...
- BZOJ刷题列表【转载于hzwer】
沿着黄学长的步伐~~ 红色为已刷,黑色为未刷,看我多久能搞完吧... Update on 7.26 :之前咕了好久...(足见博主的flag是多么emmm......)这几天开始会抽时间刷的,每天几道 ...
随机推荐
- 矩形周长(codevs 2149)
题目描述 Description N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上.它们的边都是垂直的或水平的.每个矩形可以部分或者全部覆盖其他矩形.所有的矩形组成的集合的轮廓 ...
- RQNOJ273 马棚问题
题目描述 每天,小明和他的马外出,然后他们一边跑一边玩耍.当他们结束的时候,必须带所有的马返回马棚,小明有K个马棚.他把他的马排成一排然后跟随它走向马棚,因为他们非常疲劳,小明不想让他的马做过多的移动 ...
- Topcoder 658Div2
补题风向标——>> 假装题意知道 A:暴力合成一遍了 n=s.size(); m=t.size(); ss+=s; tt+=t; if (ss==tt) or not; B:题意是给定 1 ...
- OSGI是什么
OSGI(Open Services Gateway Initiative),或者通俗点说JAVA动态模块系统,定义了一套模块应用开发的框架.OSGI容器实现方案如Knopflerfish, Equi ...
- Spring Boot应用的启动和停止(Spring Boot应用通过start命令启动)
Spring Boot,作为Spring框架对“约定优先于配置(Convention Over Configuration)”理念的最佳实践的产物,它能帮助我们很快捷的创建出独立运行.产品级别的基于S ...
- 常见machine learning模型实现
一.感知机模型 二.线性回归(Linear Regression) from numpy import * def loadData(filename): x = [] y = [] f = open ...
- hdu 3183 A Magic Lamp(给一个n位的数,从中删去m个数字,使得剩下的数字组成的数最小(顺序不能变),然后输出)
1.题目大意是,给你一个1000位的数,要你删掉m个为,求结果最小数. 思路:在n个位里面删除m个位.也就是找出n-m个位组成最小数 所以在区间 [0, m]里面找最小的数.相应的下标标号i 接着找区 ...
- 云上领跑,快人一步:华为云抢先发布Redis5.0
12月17日,华为云在DCS2.0的基础上,快人一步,抢先推出了新的Redis 5.0产品,这是一个崭新的突破.目前国内在缓存领域的发展普遍停留在Redis4.0阶段,华为云率先发布了Redis5.0 ...
- 轻量级批量Omnitty工具安装和简单使用
一.Omnitty简单介绍 在实际工作需要同时对多台docker进行批量处理,为了节省时间,这个运维轻量级工具解决此问题 二.Omnitty简单按照 下载需要安装包和依赖包: omnitty-0.3. ...
- 一个程序员对微信小程序的看法
我们公司用两周的时间开发了一款微信小程序,叫<如e支付>,大家可以去体验一下.由于接口都是写好的,所以开发起来很快.我将从4个不同的角度来介绍我对微信小程序的理解. 1.技术的角度 ...