bzoj2288 生日礼物 (线段树)
我当然想选最大的子段和啦 但要选M次 那不一定就是最好的
所以提供一个反悔的选项,我选了一段以后,就把它们乘个-1,然后再选最好的(类似于网络流的思路)
这个可以用线段树来维护,记一个区间包含左端点/右端点的最大值、最小值(因为要乘-1),还有它们的端点位置
然后一直找 直到最大值<=0
#include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
#define mp make_pair
using namespace std;
typedef long long ll;
const int maxn=1e5+,inf=0x3f3f3f3f; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
}
struct Pos{
int v,l,r;
Pos (int a=,int b=,int c=){v=a,l=b,r=c;}
};
struct Node{
Pos lmas,rmas,lmis,rmis,ma,mi,sum;
}tr[maxn<<]; bool laz[maxn<<];
int N,M,v[maxn]; bool operator <(Pos a,Pos b){
return a.v<b.v;
}
Pos operator +(Pos a,Pos b){
return Pos(a.v+b.v,a.l,b.r);
}
Pos operator -(Pos x){return Pos(-x.v,x.l,x.r);} Node operator +(Node a,Node b){
Node x;
x.sum=a.sum+b.sum;
x.lmas=max(a.lmas,a.sum+b.lmas);
x.rmas=max(b.rmas,a.rmas+b.sum);
x.lmis=min(a.lmis,a.sum+b.lmis);
x.rmis=min(b.rmis,a.rmis+b.sum);
x.ma=max(a.rmas+b.lmas,max(a.ma,b.ma));
x.mi=min(a.rmis+b.lmis,min(a.mi,b.mi));
return x;
} inline void build(int p,int l,int r){
if(l==r){
tr[p].sum=tr[p].lmas=tr[p].rmas=tr[p].lmis=tr[p].rmis=tr[p].ma=tr[p].mi=Pos(v[l],l,r);
}else{
int m=l+r>>;
build(p<<,l,m),build(p<<|,m+,r);
tr[p]=tr[p<<]+tr[p<<|];
}
} void deal(int p){
laz[p]^=;
Pos t=tr[p].lmas;
tr[p].lmas=-tr[p].lmis;tr[p].lmis=-t;
t=tr[p].rmas;
tr[p].rmas=-tr[p].rmis;tr[p].rmis=-t;
t=tr[p].ma;
tr[p].ma=-tr[p].mi;tr[p].mi=-t;
tr[p].sum=-tr[p].sum;
} inline void pushdown(int p){
if(!laz[p]) return;
deal(p<<),deal(p<<|);
laz[p]=;
} inline void rever(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) deal(p);
else{
pushdown(p);
int m=l+r>>;
if(x<=m) rever(p<<,l,m,x,y);
if(y>=m+) rever(p<<|,m+,r,x,y);
tr[p]=tr[p<<]+tr[p<<|];
}
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=N;i++)
v[i]=rd();
int ans=;
build(,,N);
for(i=;i<=M;i++){
Pos x=tr[].ma;if(x.v<=) break;
ans+=x.v;
rever(,,N,x.l,x.r);
}
printf("%d\n",ans);
return ;
}
bzoj2288 生日礼物 (线段树)的更多相关文章
- 2018.09.30 bzoj2288:生日礼物(贪心+线段树)
传送门 线段树经典题目. 每次先找到最大子段和来更新答案,然后利用网络流反悔退流的思想把这个最大字段乘-1之后放回去. 代码: #include<bits/stdc++.h> #defin ...
- 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 657 Solved: 274[Su ...
- 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)
佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为\(n\)的字符串\(s\),和\(m\)个问题.佳媛姐姐必须正确回答这\(m\)个问题, ...
- BZOJ4556 Tjoi2016&Heoi2016 字符串【后缀自动机+倍增+线段树合并】
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
随机推荐
- 【学习总结】C-翁恺老师-入门-第4周<循环控制>
[学习总结]C-翁恺老师-入门-总 1-阶乘:引入for循环 2-控制循环次数:初始化与控制条件的设置 任何一个for循环都可以写成一个while循环 for中的每一个表达式都是可以省略的:for(; ...
- I/O中断处理详细过程
1.CPU发送启动I/O设备的命令,将I/O接口中的B触发器置1,D触发器置O. 2.设备开始工作,需要向CPU传送数据时,将数据送入数据缓冲器中. 3.输入设备向I/O接口发出“设备工作结束”的信号 ...
- php开发之系统函数
一些常用的php开发之系统函数的使用,可以使我们的开发效率,事倍功半 1) BC高精度函数库 2)
- springIOC源码分析(BeanFactroy)
启动spring容器加载bean的方式有两种:最基本的容器BeanFactory和高级容器ApplicationContext.这篇文章介绍使用BeanFactory加载bean时的整个过程,当然,A ...
- Laravel 5.2+ 使用url()全局函数返回前一个页面的地址
注意:文章标题中5.2+表示该文章内容可向上兼容,适用于Laravel版本5.2及更高(目前最新为5.6),但不可向下兼容,即不适用于5.2版本以下.推荐大家花一点点时间,将自己的Laravel更新至 ...
- 使用NFS时的一些问题
当我把nfs服务端共享目录/usr/local/data/test删掉时,在nfs客户端却没办法把之前挂载在这上面的当前从机上的/usr/local/data/test删除,出现 bash: cd: ...
- Day 4-5 序列化 json & pickle &shelve
序列化: 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. 反序列化: 把字符转成内存里的数据类型. 用于序列化的两个模块.他 ...
- Day3-1 函数
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 语法: def calc(x, y): ...
- 安装 Tesserocr (填坑)
参考: https://www.imooc.com/article/45278?block_id=tuijian_wz
- java 中 Math类
package cn.liuliu.com; import java.math.BigDecimal; import java.math.BigInteger; /* * 一.Math类? * * 1 ...