bzoj 3267: KC采花&&3272&&3638&&3502 线段树
题目大意
给定一个长为n的序列,维护两种操作:
1.单点修改
2.在[l,r]这段区间中取k个互不相交的子段,使子段之和最大.
\(n \leq 50000,k \leq 20\)
题解
四倍经验.(但我的写法太丑过不了3502)
我们可以很简单地构建出一个最大费用最大流模型
把每个点拆点,然后S,T分别连接即可
但是这道题n达到50000,直接上费用流绝对T的不要不要的
我们想一下这样费用流的时候都在干什么
每次找出一个费用最大的区间...把答案加上费用之和...把所有的费用取反...
我们发现我们可以用线段树维护这个过程!
支持最大子段和查询和反转操作
所以我们维护一个最大子段和和最小子段和即可!!
啥?好像好要维护取到最大子段和和最小子段和时的端点?
啥?要维护从左端点的开始的最大子段和和从右端点开始的最大子段和?
好麻烦啊。。。估计是我写丑了...所以3502才被卡空间了...
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
struct Node{
int mx,lmx,rmx,lx,rx,plx,prx;
int mn,lmn,rmn,ln,rn,pln,prn;
int sum,rev;
Node(){
mx = lmx = rmx = -inf;
mn = lmn = rmn = inf;
sum = lx = rx = ln = rn = rev = 0;
}
inline void set(int x,int p){
rev = 0;mx = lmx = rmx = mn = lmn = rmn = sum = x;
lx=rx=plx=prx=ln=rn=pln=prn = p;
}
inline void reve(){
swap(mx,mn);swap(lmn,lmx);swap(rmn,rmx);
swap(lx,ln);swap(rx,rn);swap(plx,pln);swap(prx,prn);
mx = -mx;mn = -mn;
lmn = -lmn;lmx = -lmx;
rmx = -rmx;rmn = -rmn;
sum = -sum;rev ^= 1;
}
Node friend operator + (const Node &l,const Node &r){
Node c;
c.sum = l.sum + r.sum;
c.lmx = max(l.lmx,l.sum+max(r.lmx,0));
c.rmx = max(r.rmx,r.sum+max(l.rmx,0));
c.mx = max(max(l.mx,r.mx),max(l.rmx+max(0,r.lmx),max(l.rmx,0)+r.lmx) );
if(c.lmx == l.lmx) c.plx = l.plx;
else c.plx = r.plx;
if(c.rmx == r.rmx) c.prx = r.prx;
else c.prx = l.prx;
if(c.mx == l.mx) c.lx = l.lx,c.rx = l.rx;
else if(c.mx == r.mx) c.lx = r.lx,c.rx = r.rx;
else if(c.mx == l.rmx+r.lmx)c.lx = l.prx,c.rx = r.plx;
c.lmn = min(l.lmn,l.sum+min(r.lmn,0));
c.rmn = min(r.rmn,r.sum+min(l.rmn,0));
c.mn = min(min(l.mn,r.mn),min(l.rmn+min(0,r.lmn),min(l.rmn,0)+r.lmn) );
if(c.lmn == l.lmn) c.pln = l.pln;
else c.pln = r.pln;
if(c.rmn == r.rmn) c.prn = r.prn;
else c.prn = l.prn;
if(c.mn == l.mn) c.ln = l.ln,c.rn = l.rn;
else if(c.mn == r.mn) c.ln = r.ln,c.rn = r.rn;
else if(c.mn == l.rmn+r.lmn) c.ln = l.prn,c.rn = r.pln;
}
}T[maxn<<2];
int a[maxn];
inline void pushdown(int rt,int l,int r){
if(T[rt].rev == 0) return;
T[rt].rev = 0;
if(l == r) return;
T[rt<<1].reve();T[rt<<1|1].reve();
}
void build(int rt,int l,int r){
if(l == r){
T[rt].set(a[l],l);
return;
}int mid = l+r >> 1;
build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
T[rt] = T[rt<<1] + T[rt<<1|1];
}
void modify(int rt,int l,int r,int pos,int val){
if(l == r){
T[rt].set(val,l);
return;
}
int mid = l+r >> 1;
pushdown(rt,l,r);
if(pos <= mid) modify(rt<<1,l,mid,pos,val);
else modify(rt<<1|1,mid+1,r,pos,val);
T[rt] = T[rt<<1] + T[rt<<1|1];
}
Node query(int rt,int l,int r,int L,int R){
if(L <= l && r <= R) return T[rt];
int mid = l+r >> 1;
pushdown(rt,l,r);
if(R <= mid) return query(rt<<1,l,mid,L,R);
if(L > mid) return query(rt<<1|1,mid+1,r,L,R);
return query(rt<<1,l,mid,L,R) + query(rt<<1|1,mid+1,r,L,R);
}
void rever(int rt,int l,int r,int L,int R){
if(L <= l && r <= R){T[rt].reve();return;}
int mid = l+r >> 1;
pushdown(rt,l,r);
if(L <= mid) rever(rt<<1,l,mid,L,R);
if(R > mid) rever(rt<<1|1,mid+1,r,L,R);
T[rt] = T[rt<<1] + T[rt<<1|1];
}
struct seg{
int l,r;
seg(int l=0,int r=0){this->l=l;this->r=r;}
}sta[22];
int top,n;
inline int spfa(int l,int r,int num){
top = 0;int ret = 0;
while(num--){
Node x = query(1,1,n,l,r);
if(x.mx < 0) break;
sta[++top] = seg(x.lx,x.rx);
ret += x.mx;
rever(1,1,n,x.lx,x.rx);
}
while(top){
rever(1,1,n,sta[top].l,sta[top].r);
--top;
}
return ret;
}
int main(){
read(n);
for(int i=1;i<=n;++i) read(a[i]);
build(1,1,n);
int m;read(m);
int op,l,r,k;
while(m--){
read(op);read(l);read(r);
if(op == 0){
modify(1,1,n,l,r);
}else{
read(k);
printf("%d\n",spfa(l,r,k));
}
}
getchar();getchar();
return 0;
}
bzoj 3267: KC采花&&3272&&3638&&3502 线段树的更多相关文章
- bzoj3272: Zgg吃东西&&3267: KC采花
口胡 我们容易得到一个费用流的做法,流出k的流量分配给各个点,各个点向下一个点流费用为它的价值的边,然后汇总到ed 观察发现对于流一次,相当于选择了一个区间 如果流了反向边,相当于减去了这一段 可以用 ...
- BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- 洛谷 P2056 BZOJ 2743 [HEOI2012]采花
//表示真的更喜欢洛谷的题面 题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 ...
- BZOJ 2743: [HEOI2012]采花
2743: [HEOI2012]采花 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 2056 Solved: 1059[Submit][Status ...
- BZOJ 2743: [HEOI2012]采花( 离线 + BIT )
处理出每个数下一个出现的位置, 然后按左端点排序回答询问.处理当前数去除的影响 ------------------------------------------------------------ ...
- BZOJ 2743: [HEOI2012]采花 离线树状数组
2743: [HEOI2012]采花 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2743 Description 萧芸斓是Z国的公主, ...
- BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...
- [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】
题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...
随机推荐
- java 匿名类和匿名方法
package com.test; interface product{ int getPrice(); } public class News { /** * @param args */ publ ...
- jdbcTemplaate queryForObject的两个易混淆的方法
JdbcTemplate中有两个可能会混淆的queryForObject方法: 1. Object queryForObject(String sql, Object[] args, Class ...
- xml 操作
/////////////////////////////////jaxp对xml文档进行解析/////////////////////////////////////////// 要操作的xml文件 ...
- 【问】Windows下C++局部变量在内存中的分布问题
原本是为了看看C++对象模型中子对象赋值给一个父对象和父类型指针指向的域时,到底会不会切割,就打开codebloks写了下面的代码,编译器选的是GNU. #define DEBUG(X) std::c ...
- mysql日期格式转化
select DATE_FORMAT( '20170701', '%Y-%m-%d'); 先挖坑
- 【Python】selenium调用IE11浏览器,报错“找不到元素”NoSuchWindowException: Message:Unable to find element on closed window
当编写自动化脚本,定位浏览器元素时,报如下错误: 代码: >>> # coding=utf-8 >>> from selenium import webdriver ...
- Android-彻底地理解Binder
转自:https://blog.csdn.net/huachao1001 https://blog.csdn.net/huachao1001/article/details/51504469 你是不是 ...
- 【BZOJ2789】[Poi2012]Letters 树状数组
[BZOJ2789][Poi2012]Letters Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符 ...
- 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP
[BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...
- 使用Scrapy采集
1.有些站点通过robot协议,防止scrapy爬取,就会出现如下问题: DEBUG: Forbidden by robots.txt: <GET http://baike.baidu.com/ ...