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......)这几天开始会抽时间刷的,每天几道 ...
随机推荐
- Linux Awk使用案例总结
知识点: 1)数组 数组是用来存储一系列值的变量,可通过索引来访问数组的值. Awk中数组称为关联数组,因为它的下标(索引)可以是数字也可以是字符串. 下标通常称为键,数组元素的键和值存储在Awk程序 ...
- 【ZJOI2017 Round1练习&BZOJ4765】D1T3 普通计算姬(主席树,分块)
题意: 思路:分块 使用树状数组维护sum[i]的前缀和 使用主席树维护root到u的路径上点的编号出现的个数 每次操作如果是修改就加入队列 如果是询问,考虑块内操作对询问的影响,每次在x点加上y会使 ...
- 《TCP/IP详解卷1:协议》——第1章:概述(转载)
1.引言 很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但TCP/IP协议族允许它们互相进行通信.TCP/IP起源于60年代末美国政府资助的一个分组交换网络研究项目,到90年代已发展 ...
- 2016 ACM-ICPC CHINA-Final
补题进度:10/12 地址:http://codeforces.com/gym/101194 A(签到) 略 B(数位DP) 题意: 定义一个01字符串为good串当且仅当将其奇数位或者偶数位单独拎出 ...
- Mac shell 小脚本开发(转)
大多数程序员都喜欢偷懒的,我也不例外.相信好多Android开发的coder 在网络http请求方面,会浪费很多时间在接口调试这里..有时候,自己写了一个小测试,行还好,不行的话,还要跟写后台的哥们一 ...
- Antivius for Linux
http://www.clamav.net/ https://www.avast.com/zh-cn/linux-server-antivirus http://www.f-prot.com/ ...
- 在DIV中自己主动换行
word-break:break-all和word-wrap:break-word都是能使其容器如DIV的内容自己主动换行. 它们的差别就在于: 1,word-break:break-all 比如di ...
- C#调用国家气象局天气预报接口
原文:C#调用国家气象局天气预报接口 一.需求 最近,刚好项目中有天气预报查询功能的需求,要求录入城市名称,获取该城市今日天气信息及相关气象生活辅助信息等. 例如:查询北京市天气 结果为: 今日北京天 ...
- html2canvas 导出包含滚动条的内容
import html2canvas from 'html2canvas'; exportPDF() { // 导出为 pdf let dom = document.querySelector('yo ...
- Python爬虫开发【第1篇】【多线程爬虫及案例】
糗事百科爬虫实例: 地址:http://www.qiushibaike.com/8hr/page/1 需求: 使用requests获取页面信息,用XPath / re 做数据提取 获取每个帖子里的用户 ...