题目链接

各种zz错误。。简直了

/*
19604kb 36292ms
题意:选$k$段不相交的区间,使其权值和最大。
朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk^2logn)->GG
考虑费用流:建一条n+1个点的链(点权设在边上,故需n+1个点),链上每个点和S、T连边,相邻点连边
这样数列中的区间和每条增广路一一对应
每次最多增广k次,O(nmk)->still GG
考虑费用流这一过程的实质:每次增广相当于贪心,本质上只有两种情况:
选取一段(新增一个区间)、从已选的某个区间中删除一段
使用线段树实现这个贪心过程,支持(单点修改、)区间查询最大子段和(选取)、区间取反(相当于删除)
这样每次查询修改k次,最后把修改逐一复原
O(mklogn)
注: 1.需要维护一个区间最小值,因为取反后原区间最小值就成了最大值
2.用堆式存储要更好,因为查找最大子段和需要得到位置,这样直接返回一个结构体
(1)根节点是0
(2)另外用Merge代替Update可以方便地用在Query()中 (好吧其实再写个函数无所谓)
(3)如果存左右儿子的话别忘了合并时也改掉 and tag..
3.重载'+'后左右两运算数不要反
4.Reverse()必须一次到完整区间,因为上边的节点需要下边的完整信息(脑补)
*/
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define gc() getchar()
const int N=1e5+5; int n,m,tp;
//char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
struct Node
{
struct Node2
{
int l,r,val;
inline friend Node2 operator +(const Node2 &x,const Node2 &y)
{
Node2 tmp;
tmp.l=x.l, tmp.r=y.r, tmp.val=x.val+y.val;
return tmp;
}
inline friend bool operator <(const Node2 &x,const Node2 &y)
{
return x.val<y.val;
}
}sum,lmn,rmn,lmx,smx,smn,rmx;
int ls,rs;
bool tag;
inline void Init(int p,int v)
{
sum.val=lmx.val=rmx.val=lmn.val=rmn.val=smx.val=smn.val=v,
sum.l=lmx.l=rmx.l=lmn.l=rmn.l=smx.l=smn.l=p;
sum.r=lmx.r=rmx.r=lmn.r=rmn.r=smx.r=smn.r=p;
ls=rs=-1, tag=0;
}
}node[N<<1],sk[30];
struct Seg_Tree
{
int tot;
Node Merge(const Node &x,const Node &y)
{
Node rt;
// printf("%d,%d(%d,%d) %d,%d(%d,%d)\n",x.smx.val,y.smx.val,x.smx.l,y.smx.r,x.rmx.val,y.lmx.val,x.rmx.l,y.lmx.r);
rt.lmx=std::max(x.lmx,x.sum+y.lmx);
rt.rmx=std::max(y.rmx,x.rmx+y.sum);//!
rt.lmn=std::min(x.lmn,x.sum+y.lmn);
rt.rmn=std::min(y.rmn,x.rmn+y.sum);
rt.smx=std::max(x.rmx+y.lmx,std::max(x.smx,y.smx));
rt.smn=std::min(x.rmn+y.lmn,std::min(x.smn,y.smn));
rt.sum=x.sum+y.sum;
rt.tag=0;//!
return rt;
}
void Rev(int rt)
{
node[rt].tag^=1;
std::swap(node[rt].lmx,node[rt].lmn), std::swap(node[rt].rmx,node[rt].rmn),
std::swap(node[rt].smx,node[rt].smn),
node[rt].lmx.val*=-1, node[rt].lmn.val*=-1,
node[rt].rmx.val*=-1, node[rt].rmn.val*=-1,
node[rt].smx.val*=-1, node[rt].smn.val*=-1,
node[rt].sum.val*=-1;
}
inline void PushDown(int rt)
{
Rev(node[rt].ls), Rev(node[rt].rs);
node[rt].tag=0;
}
void Build(int l,int r)
{
int p=tot++;
if(l==r) {node[p].Init(l,read()),node[p].ls=node[p].rs=-1; return;}
int m=l+r>>1;
node[p].ls=tot, Build(l,m),
node[p].rs=tot, Build(m+1,r);
int ls=node[p].ls,rs=node[p].rs;
node[p]=Merge(node[ls],node[rs]);
node[p].ls=ls, node[p].rs=rs;
// printf("%d:%d~%d mx:%d(%d~%d) sum:%d\n",p+1,l,r,node[p].smx.val,node[p].smx.l,node[p].smx.r,node[p].sum.val);
}
void Modify(int l,int r,int rt,int p,int v)
{
if(l==r) {node[rt].Init(l,v); return;}
if(node[rt].tag) PushDown(rt);
int m=l+r>>1,ls=node[rt].ls,rs=node[rt].rs;
if(p<=m) Modify(l,m,ls,p,v);
else Modify(m+1,r,rs,p,v);
node[rt]=Merge(node[ls],node[rs]);
node[rt].ls=ls, node[rt].rs=rs;
}
void Reverse(int l,int r,int rt,int L,int R)
{
if(L==l && r==R) {Rev(rt); return;}//!
if(node[rt].tag) PushDown(rt);
int m=l+r>>1,ls=node[rt].ls,rs=node[rt].rs;
if(L<=m)//!
if(m<R) Reverse(l,m,ls,L,m),Reverse(m+1,r,rs,m+1,R);
else Reverse(l,m,ls,L,R);
else Reverse(m+1,r,rs,L,R);
node[rt]=Merge(node[ls],node[rs]);
node[rt].ls=ls, node[rt].rs=rs;
}
Node Query(int l,int r,int rt,int L,int R)
{
// WR: if(L<=l && r<=R) return node[rt];
if(L==l && r==R) return node[rt];//!
if(node[rt].tag) PushDown(rt);
int m=l+r>>1;
if(L<=m)//!
if(m<R) return Merge(Query(l,m,node[rt].ls,L,m),Query(m+1,r,node[rt].rs,m+1,R));
else return Query(l,m,node[rt].ls,L,R);
else return Query(m+1,r,node[rt].rs,L,R);
}
// void Print(int l,int r,int p)
// {
// if(l==r) return;
// if(node[p].tag) PushDown(p);
// int m=l+r>>1;
// Print(l,m,node[p].ls),
// printf("P:%d:%d~%d mx:%d(%d~%d) sum:%d\n",p+1,l,r,node[p].smx.val,node[p].smx.l,node[p].smx.r,node[p].sum.val);
// Print(m+1,r,node[p].rs);
// }
}t; int main()
{
#ifndef ONLINE_JUDGE
freopen("3638.in","r",stdin);
#endif n=read();
t.Build(1,n);//t.Print(1,n,0);
m=read();
int opt,p,k,l,r,res; Node pos;
while(m--)
{
opt=read();
if(!opt) p=read(),k=read(),t.Modify(1,n,0,p,k);
else
{
l=read(),r=read(),k=read(),res=0;
while(k--)
{
pos=t.Query(1,n,0,l,r);
// printf("%d~%d val:%d\n",pos.smx.l,pos.smx.r,pos.smx.val);
if(pos.smx.val<0) break;
res+=pos.smx.val;
sk[++tp]=pos;//反转前先入栈
t.Reverse(1,n,0,pos.smx.l,pos.smx.r);//t.Print(1,n,0);
}
printf("%d\n",res);
while(tp)
t.Reverse(1,n,0,sk[tp].smx.l,sk[tp].smx.r),--tp;
// t.Print(1,n,0);
}
}
return 0;
}

BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)的更多相关文章

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

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

  2. BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=3836 (Codeforces) http://codeforces.com ...

  3. Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]

    洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...

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

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

  5. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...

  6. BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分

    题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...

  7. BZOJ 1920 Luogu P4217 [CTSC2010]产品销售 (模拟费用流、线段树)

    题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=1920 (luogu) https://www.luogu.org/prob ...

  8. Maximum Subsequence Sum【最大连续子序列+树状数组解决】

    Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i < ...

  9. BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图

    Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢 ...

随机推荐

  1. 泰克TDS1000B示波器使用说明

    1.前言 本文主要根据泰克官方网站TDS1000B/TDS2000B使用教程视频进行整理. 2.认识你的示波器 TDS1000B带宽从40MHZ到200MHZ,采样率高达2Gbps

  2. 如何在linux系统下配置无线网卡?【转】

    转自:http://www.jb51.net/LINUXjishu/61315.html 本文介绍在Linux 命令行界面中手动配置无线网卡的方法.目前流行的多数发行版都支持用图形界面的network ...

  3. mac安装pyspider报错

    (env)$ pip3 uninstall pycurl (env)$ pip3 install --upgrade pip (env)$ export LDFLAGS=-L/usr/local/op ...

  4. vue中遇到的坑!!!!!

    一 .vue安装的坑 报错时的常见问题 1.cnpm install 模块名 –save-dev(关于环境的,表现为npm run dev 启动不了)cnpm install 模块名 –save(关于 ...

  5. python系统编码转换

    # coding:gbk import sys import locale def p(f): print '%s.%s(): %s' % (f.__module__, f.__name__, f() ...

  6. C++ virtual函数重写,在继承的时候没有在函数前写virtual关键字也依然是虚函数吗?

    比如: class Base { Base() {}; ~Base() {}; virtual void Init(); }; class Derived:public Base { virtual ...

  7. 为cobbler自动化安装系统工具添加epel源

    关于cobbler的安装及部署,参考:CentOS 6.5自动化运维之基于cobbler服务的自动化安装操作系统详解http://blog.csdn.net/reblue520/article/det ...

  8. python3之MongoDB

    1.MongoDB简介 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提供可 ...

  9. Buffer学习笔记.

    前言 JavaScript 对于字符串的操作十分便捷,无论是单字节字符还是宽字节字符,都会认为是一个字符.对字符串的简单操作和DOM操作基本上已经可以满足前端工程需求,但Node很多时候需要处理文件和 ...

  10. LeetCode(46):全排列

    Medium! 题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [ ...