首页 > 其他分享 >POJ3017 Cut the Sequence

POJ3017 Cut the Sequence

时间:2024-07-06 19:08:14浏览次数:19  
标签:dots Cut POJ3017 Sequence int max leq maxn multiset

POJ3017 Cut the Sequence

题目大意

给定一个一个长度为 \(N\) 的序列 \(A\),要求把该序列划分成若干段,其中每一段中的数的和不大于 \(M\),现在需要使得每一段中数的最大值的和最小,求该最小值。

\[0 \leq n \leq 10^5 \\ 0 \leq m \leq 10^{11} \\ 0 \leq a_i \leq 10^6 \]

解题思路

可以想到动态规划,设 \(f(i)\) 表示考虑前 \(i\) 位的划分时的答案。

容易有状态转移方程:

\[f(i) = \max\{ f(j) + max\{a_{j+1} \dots a_i\} \},(sum\{a_{j+1} \dots a_i\} \leq m) \]

有一个比较显然的性质,\(f\) 是单调不降的。

故我们做出以下思考,设 \(max\{a_{j+1} \dots a_i\} = a_k\),即最大值下标为 \(k\)。

那么:

\[\begin{aligned} f(i) &= \max\{f(j) + a_k\} \\ &= \max\{f(j)\} + a_k \end{aligned} \]

根据上面提到的性质,此时,\(j\) 当然越小越好。

总结一下,即,对于 \(a_k = max\{a_{j+1} \dots a_i\}\),\(j\)最小时转移 \(f(i) = f(j) + a_k\)。

形象的说,对于 \(a_k\) 我们取其 管辖区间 (即使得其为最大值的区间)的左端点转移。

我们考虑如何求出这些区间。

我们从前往后依次遍历原序列,同时维护一个下降的单调队列,对于其中的 \(q_i\) 其的 管辖区间 即为 \([q_{i-1}+1,i]\),其余的点无法成为最大值,不需要转移。

对于队头元素,其 管辖区间 的左端点即满足转移方程中的条件 \(sum\{a_{j+1} \dots a_i\} \leq m\),这个用前缀和加一个指针就可以做到(利用前缀和的单调性)。

我们得知了队列中的每一个点的 管辖区间 的左端点,用一个 multiset 动态维护(在加入和弹出队列时操作 multiset)。

值得注意的是,队首元素的左端点随 \(i\) 变化,不使用 multiset 维护,单独转移。

参考代码

//#include<bits/stdc++.h>
#include<set>
#include<cstdio>
using namespace std;
#define int long long
const int maxn=1e5;
int n,m;
int a[maxn+5];
int s[maxn+5];
int f[maxn+5];
int q[maxn+5],l,r;
multiset<int> c;
signed main(){
	int k;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]),s[i]=s[i-1]+a[i];
	k=0,l=1,r=0;
	for(int i=1;i<=n;i++){
		if(a[i]>m){puts("-1");return 0;}
		while(s[i]-s[k]>m) k++;
		while(l<=r&&a[q[r]]<=a[i]){
			if(l<r) c.erase(c.find(f[q[r-1]]+a[q[r]]));
			r--;
		}
		q[++r]=i;
		if(l<r) c.insert(f[q[r-1]]+a[q[r]]);
		while(l<=r&&q[l]<=k){
			if(l<r) c.erase(c.find(f[q[l]]+a[q[l+1]]));
			l++;
		}
		f[i]=f[k]+a[q[l]];
		if(l<r) f[i]=min(f[i],*c.begin());
	}
	printf("%lld",f[n]);
	return 0;
}

标签:dots,Cut,POJ3017,Sequence,int,max,leq,maxn,multiset
From: https://www.cnblogs.com/DeepSeaSpray/p/18287613

相关文章

  • Leetcode 1143. Longest Common Subsequence
    ProblemGiventwostringstext1andtext2,returnthelengthoftheirlongestcommonsubsequence.Ifthereisnocommonsubsequence,return0.Asubsequenceofastringisanewstringgeneratedfromtheoriginalstringwithsomecharacters(canbenone......
  • kaggle运行报错RuntimeError: cutlassF: no kernel found to launch!
    项目场景:项目场景:使用原始Llama3推理,到这里都是能行的!pipinstall-qmodelscopeimporttorchfrommodelscopeimportsnapshot_download,AutoModel,AutoTokenizerimportosmodel_dir=snapshot_download('LLM-Research/Meta-Llama-3-8B-Instruct',cache_dir='/r......
  • 四种封装 ThreadPoolExecutor 的线程池的使用以及直接使用 ThreadPoolExecutor ,优缺点
    池化思想:线程池、字符串常量池、数据库连接池提高资源的利用率下面是手动创建线程和执行任务过程,可见挺麻烦的,而且线程利用率不高。手动创建线程对象执行任务执行完毕,释放线程对象线程池的优点:提高线程的利用率提高程序的响应速度便于统一管理线程对象可以控制最大并发......
  • Python多线程-线程池ThreadPoolExecutor
    1.线程池不是线程数量越多,程序的执行效率就越快。线程也是一个对象,是需要占用资源的,线程数量过多的话肯定会消耗过多的资源,同时线程间的上下文切换也是一笔不小的开销,所以有时候开辟过多的线程不但不会提高程序的执行效率,反而会适得其反使程序变慢,得不偿失。为了防止无尽的线程......
  • [1022] Activate specific apps using keyboard shortcuts
    Thisisaverygoodone!!! TaskbarShortcutKeys:Ifanappispinnedtoyourtaskbar,youcanusethefollowingshortcut:PressWin+1toactivatethefirstprogramonthetaskbar(orlaunchitifit’snotopen).Similarly,Win+2activatesthesec......
  • Plugin开发基本知识点 IPluginExecutionContext, iOrganization Service
    IPluginExecutionContext`IPluginExecutionContext`接口在MicrosoftDynamics365插件开发中用于获取有关当前插件执行上下文的信息。它提供了丰富的属性和方法,帮助开发者在插件执行时获取与当前操作相关的各种数据和元数据。以下是`IPluginExecutionContext`的一些主要功能和属......
  • Atcoder ABC091D Two Sequences
    首先根据\(\operatorname{xor}\),就想到拆成二进制的\(a_{i,w},b_{i,w}\)来处理。类似竖式加法,考虑把得到的结果\(c_{w}\)分为\(a_{i,w}+b_{j,w}+x\),其中\(x\)就是上一位的进位。进一步的,发现对于总的\(c_{w}\),\(a_{i,w},b_{j,w}\)肯定都在这个位置加了\(......
  • 完美解决stack Error: Can‘t find Python executable “python“, you can set the P
    解决方案:node版本太高了,我同时说他环境是node14的,我就来了个14.18的,结果还是不是,应该是14系列,我的二级版本还是高了。python什么的安装了没什么用!!!一步一步来,先解决第一部分:错误提示的意思是说我没有python,我电脑里确实没有下载python,但实际上不用下载python也能解决这个问题。......
  • Cobra - Flags are parsed after rootCmd.Execute()
     root.go:funcinit(){rootCmd.PersistentFlags().BoolVarP(&enableLogging,"log","l",true,"Logginginformation")fmt.Println("*************************",enableLogging)}funcExecute(){err:......
  • 9.2JavaEE——JDBCTemplate的常用方法(一)excute()方法
    execute()方法用于执行SQL语句,其语法格式如下:jdTemplate.execute("SQL语句");下面以创建数据表的SQL语句为例,来演示excute()方法的使用,具体步骤如下。1、创建数据库        在MySQL中,创建一个名为spring的数据库。 mysql>createdatabasespring;QueryOK,1......