【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 ...
随机推荐
- NOI2018 游记
day-2 飞向长沙 上午收拾了收拾东西,下载了动画<爱吃拉面的小泉同学>的前五集. 吃过午饭,就准备坐车去运城机场.高铁飞速,转眼间就到了.我没坐过几次飞机,而且比较恐飞,就很难受qwq ...
- 今天买了个pro,开始ios开发
今天买了个mac pro 开始ios开发啦,爽!
- 「题目代码」P1007~P1012(Java)
1007 C基础-计负均正 import java.util.*; import java.io.*; public class Main { public static void main(Stri ...
- 如何用Fiddler 拦住RestAssured发出的请求
用RestAssured 发出的请求并不能直接被fiddler 拦截,可以在初始化的时候做出如下配置: RestAssured.proxy("localhost", 8888); ...
- OpenStack配置虚拟机vcpu绑定步骤 转至元数据结尾
. Changed in compute node: 给宿主机预留资源: 宿主机可用cpu:cpuid – cpuid 宿主机可用内存:25G #vim /etc/nova/nova.conf vcp ...
- 0.爬虫 urlib库讲解 urlopen()与Request()
# 注意一下 是import urllib.request 还是 form urllib import request 0. urlopen() 语法:urllib.request.urlopen(u ...
- 去西交大考PAT认证
这周六去了西交大去考浙大PAT认证,为什么要写这个博客呢.因为...我不是西交大的学生,找考场就花了我很多时间,各种搜都找不到PAT的考场在哪. 在此记录一下,希望有有缘人再去西交大考试,可以少走点弯 ...
- python进制转换(二进制、十进制和十六进制)及注意事项
使用内置函数实现进制转换实现比较简单,主要用到以下函数: bin().oct().int().hex() 下面分别详解一下各个函数的使用(附实例) 第一部分:其他进制转十进制 1.二进制转十进制 使用 ...
- JAVA-I/O流任务
作业地址 5. Scanner基本概念组装对象 编写public static List readStudents(String fileName)从fileName指定的文本文件中读取所有学生,并将 ...
- lintcode-106-排序列表转换为二分查找树
106-排序列表转换为二分查找树 给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树 样例 标签 递归 链表 思路 类似于二分查找,每次将链表二分,中间节点作为根节点,在建立左子树 ...