【Foreign】划分序列 [线段树][DP]
划分序列
Time Limit: 20 Sec Memory Limit: 256 MB
Description
Input
Output
仅一行一个整数表示答案。
Sample Input
9 4
1 1 1 3 2 2 1 3 1
Sample Output
5
HINT
Main idea
将序列分为若干段,使得和最大的那一段最小,值可以为负。
Source
首先,显然都想到了二分答案。
我们先把都为正数或负数的情况写了:Ai>=0的时候求出最小的划分段数x,若x<=K则表示当前答案可行;Ai<=0的时候求出最大的划分段数x,若x>=K则表示当前答案可行。然后再打了暴力,接着我们对拍一下,惊讶地发现了一个规律:若最小划分段数为L,最大划分段数为R,当L<=K<=R时则可以更新。
然后我们用DP来求L和R,也就是:若一段的和满足<=mid,则可以分为一段。
然后我们发现,可以用线段树优化寻找1~i-1中的最小值或最大值,这样判断就可以满足效率了。
Code
- #include<iostream>
- #include<algorithm>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #include<cmath>
- #include<vector>
- using namespace std;
- typedef long long s64;
- const int INF = ;
- const int ONE = 5e4+;
- int n,block;
- int L,R;
- int x,sum[ONE],s[ONE];
- int li[ONE],li_num;
- int f_min[ONE],f_max[ONE];
- int res_min,res_max;
- int Zero;
- int get()
- {
- int res=,Q=; char c;
- while( (c=getchar())< || c>)
- if(c=='-')Q=-;
- if(Q) res=c-;
- while((c=getchar())>= && c<=)
- res=res*+c-;
- return res*Q;
- }
- namespace Seg
- {
- struct power
- {
- int minn;
- int maxx;
- }Node[ONE];
- void Build(int i,int l,int r)
- {
- Node[i].minn = INF;
- Node[i].maxx = -INF;
- if(l==r) return;
- int mid=(l+r)>>;
- Build(i<<,l,mid); Build(i<<|,mid+,r);
- }
- void Update(int i,int l,int r,int L,int x,int PD)
- {
- if(l==r)
- {
- if(!PD) Node[i].minn = x;
- else Node[i].maxx = x;
- return;
- }
- int mid=(l+r)>>;
- if(L<=mid) Update(i<<,l,mid,L,x,PD);
- else Update(i<<|,mid+,r,L,x,PD);
- Node[i].minn = min(Node[i<<].minn, Node[i<<|].minn);
- Node[i].maxx = max(Node[i<<].maxx, Node[i<<|].maxx);
- }
- void Query(int i,int l,int r,int L,int R)
- {
- if(L<=l && r<=R)
- {
- res_min=min(res_min, Node[i].minn);
- res_max=max(res_max, Node[i].maxx);
- return;
- }
- int mid=(l+r)>>;
- if(L<=mid) Query(i<<,l,mid,L,R);
- if(mid+<=R) Query(i<<|,mid+,r,L,R);
- }
- }
- int Check(int mid)
- {
- Seg::Build(,,li_num);
- Seg::Update(,,li_num, Zero,,);
- Seg::Update(,,li_num, Zero,,);
- for(int i=;i<=n;i++)
- {
- int pos = lower_bound(li+,li+li_num+,sum[i] - mid) - li;
- res_min = INF; res_max = -INF; Seg::Query(,,li_num, ,pos);
- f_min[i] = res_min + ;
- f_max[i] = res_max + ;
- Seg::Update(,,li_num, s[i],f_min[i],);
- Seg::Update(,,li_num, s[i],f_max[i],);
- }
- return (f_min[n]<=block && block<=f_max[n]);
- }
- int main()
- {
- n=get(); block=get();
- li[++li_num] = ;
- for(int i=;i<=n;i++)
- {
- x=get();
- li[++li_num] = sum[i] = sum[i-] + x;
- if(x < ) L+=x; else R+=x;
- }
- sort(li+,li+li_num+);
- li_num = unique(li+,li+li_num+) - li - ;
- for(int i=;i<=n;i++)
- s[i]=lower_bound(li+,li+li_num+, sum[i]) - li;
- Zero = lower_bound(li+,li+li_num+, ) - li;
- while(L < R - )
- {
- int mid=(L+R)>>;
- if(Check(mid)) R = mid;
- else L = mid;
- }
- if(Check(L)) printf("%d",L);
- else printf("%d",R);
- }
【Foreign】划分序列 [线段树][DP]的更多相关文章
- hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- 【Foreign】阅读 [线段树][DP]
阅读 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 0 10 4 10 2 3 10 8 ...
- Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)
[题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...
- bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1095 [题意] 给定一棵树,树上颜色或白或黑而且可以更改,多个询问求最远黑点之间的距离 ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 【BZOJ】1095: [ZJOI2007]Hide 捉迷藏 括号序列+线段树
[题目]BZOJ 1095 [题意]给定n个黑白点的树,初始全为黑点,Q次操作翻转一个点的颜色,或询问最远的两个黑点的距离,\(n \leq 10^5,Q \leq 5*10^5\). [算法]括号序 ...
- Snacks HDU 5692 dfs序列+线段树
Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...
- YbtOJ#463-序列划分【二分答案,线段树,dp】
正题 题目链接:https://www.ybtoj.com.cn/problem/463 题目大意 给出长度为\(n\)的序列\(A,B\).要求划分成若干段满足 对于任何\(i<j\),若\( ...
- HDU 4521 小明系列问题——小明序列 (线段树维护DP)
题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #in ...
随机推荐
- Ubantu修改主机名详细步骤
使用vmWare创建的Ubantu虚拟主机,默认的主机名均为Ubantu,通过修改主机名的使得分布式集群操作变得方便.具体步骤如下: 1.查看虚拟机的主机名:打开终端,使用 hostname 命令,回 ...
- CCF-NOIP-2018 提高组(复赛) 模拟试题(五)
T1 相遇 [问题描述] 在一场奇怪的梦里,小 Y 来到了一个神奇的国度.这个国度可以用一根数轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处.小 Y 有两种方式移动, 一种叫做步行, 一种 ...
- (原创)不过如此的 DFS 深度优先遍历
DFS 深度优先遍历 DFS算法用于遍历图结构,旨在遍历每一个结点,顾名思义,这种方法把遍历的重点放在深度上,什么意思呢?就是在访问过的结点做标记的前提下,一条路走到天黑,我们都知道当每一个结点都有很 ...
- LeetCode 23 ——合并 K 个排序链表
1. 题目 2. 解答 2.1. 方法一 在 合并两个有序链表 的基础上,我们很容易想到第一种解法,首先我们将第一个链表和第二个链表合并成一个新的链表,然后再往后依次合并接下来的每个链表即可. 假设每 ...
- DFS(3)——poj1321棋盘问题
一.题目回顾 题目链接:棋盘问题 Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于 ...
- sendto函数的坑
测试unix数据报套接字时,一个程序收,一个程序发,分别绑定自己的socket.结果在收的部分,返回的发送方的地址总是空的,但是返回的地址长度又是对的. ) { bzero(&clientad ...
- 个人作业Week3-案例分析(201521123103 吴雅娟)
根据博客要求,写一篇个人随笔 参考来自: http://www.cnblogs.com/xinz/archive/2012/03/26/2417699.html: http://www.cnblogs ...
- 基于log4j的消息流的实现之一消息获取
需求: 目前的程序中都是基于log4j来实现日志的管理,想要获取日志中的一部分消息,展示给用户. 约束: 由于程序中除了自己开发的代码,还会有层层依赖的第三方jar中的日志输出.需要展示给用户的消息, ...
- hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)
Cyclic Tour Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total ...
- P4467 [SCOI2007]k短路
题目描述 有 n 个城市和 m 条单向道路,城市编号为 1 到 n .每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此 n 和 m 满足 m \le n(n-1)m≤n(n−1 ...