【UOJ#246】套路(动态规划)

【UOJ#246】套路(动态规划)

题面

UOJ

题解

假如答案的选择的区间长度很小,我们可以做一个暴力\(dp\)计算\(s(l,r)\),即\(s(l,r)=min(s(l+1,r),s(l,r-1),abs(a_r-a_l))\)。
我们发现\(s(l,r)\le \frac{m}{r-l+1}\),那么当长度足够大的时候\(s(l,r)\)的取值很小。
所以我们对于询问分治处理,当长度小于\(\sqrt m\)时,直接\(dp\)计算贡献。
否则,当长度大于\(\sqrt m\)时,枚举\(s(l,r)\)的值,对于每个右端点计算其合法的最大左端点。
复杂度\(O(n\sqrt m)\)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 200200
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
ll ans;
int a[MAX],n,m,k,blk,s[MAX],lst[MAX],pos[MAX];
int main()
{
    n=read();m=read();k=read();blk=sqrt(m)+1;
    for(int i=1;i<=n;++i)a[i]=read(),s[i]=m;
    for(int l=2;l<=blk;++l)
    {
        for(int j=1;j+l-1<=n;++j)s[j]=min(abs(a[j]-a[j+l-1]),min(s[j],s[j+1]));
        if(l>=k)for(int j=1;j+l-1<=n;++j)ans=max(ans,1ll*(l-1)*s[j]);
    }
    for(int i=1;i<=n;lst[a[i]]=i,++i)
        for(int j=0,r=0;j<=blk;++j)
        {
            if(a[i]-j>=1)pos[j]=max(pos[j],lst[a[i]-j]);
            if(a[i]+j<=m)pos[j]=max(pos[j],lst[a[i]+j]);
            if(pos[j]>r&&i-r>=k)ans=max(ans,1ll*(i-r-1)*j);
            r=max(r,pos[j]);
        }
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/10283683.html

时间: 2024-08-28 13:13:06

【UOJ#246】套路(动态规划)的相关文章

【UOJ#22】【UR #1】外星人(动态规划)

[UOJ#22][UR #1]外星人(动态规划) 题面 UOJ 题解 一道简单题? 不难发现只有按照从大往小排序的顺序选择的才有意义,否则先选择一个小数再去模一个大数是没有意义的. 设\(f[i][j]\)表示考虑了前\(i\)个数,模完之后是\(j\)的方案数. 转移的时候枚举这个数是模还是不模,如果不模的话就要把它放到后面某个小数的后面,方案数是\(n-i\). #include<iostream> #include<cstdio> #include<cstdlib>

【UOJ#50】【UR #3】链式反应(分治FFT,动态规划)

[UOJ#50][UR #3]链式反应(分治FFT,动态规划) 题面 UOJ 题解 首先把题目意思捋一捋,大概就是有\(n\)个节点的一棵树,父亲的编号大于儿子. 满足一个点的儿子有\(2+c\)个,其中\(c\in A\),且\(c\)个儿子是叶子,另外\(2\)个存在子树,且两种点的链接的边是不同的,求方案数. 那么就考虑一个暴力\(dp\),设\(f[i]\)表示有\(i\)个节点的树的个数. 那么枚举它两个有子树的子树大小,然后把编号给取出来,得到: \[f[i]=\frac{1}{2}

告别动态规划,连刷 40 道题,我总结了这些套路,看不懂你打我(万字长文)

动态规划难吗?说实话,我觉得很难,特别是对于初学者来说,我当时入门动态规划的时候,是看 0-1 背包问题,当时真的是一脸懵逼.后来,我遇到动态规划的题,看的懂答案,但就是自己不会做,不知道怎么下手.就像做递归的题,看的懂答案,但下不了手,关于递归的,我之前也写过一篇套路的文章,如果对递归不大懂的,强烈建议看一看:为什么你学不会递归,告别递归,谈谈我的经验 对于动态规划,春招秋招时好多题都会用到动态规划,一气之下,再 leetcode 连续刷了几十道题 之后,豁然开朗 ,感觉动态规划也不是很难,今

动态规划: 套路之推导公式 黑暗字符串 牛客

[编程题] 暗黑的字符串 一个只包含'A'.'B'和'C'的字符串,如果存在某一段长度为3的连续子串中恰好'A'.'B'和'C'各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的.例如: BAACAACCBAAA 连续子串"CBA"中包含了'A','B','C'各一个,所以是纯净的字符串 AABBCCAABB 不存在一个长度为3的连续子串包含'A','B','C',所以是暗黑的字符串 你的任务就是计算出长度为n的字符串(只包含'A'.'B'和'C'),有多少个是暗黑的字符串.

UOJ#346. 【清华集训2017】某位歌姬的故事 动态规划

原文链接www.cnblogs.com/zhouzhendong/p/UOJ346.html 题解 首先按照 $m_i$ 的大小排个序. 如果某一个区间和一个 m 值比他小的区间有交,那么显然可以将这个区间控制的区域删除掉重合的那一段. 如果一个区间被删没了,那么显然答案为 0 . 在这个处理之后,一个区间可能会变得不连续.那么我们就将它前后相连,变成连续的. 接下来问题变成了对每一种权值的区间算答案. 这个东西离散化之后大力DP即可. 注意特判权值为 1 的区间. 写起来好像有点麻烦. 时间复

naive的动态规划套路总结

\(O(nlogn)\)求长度为\(n\)的数列的\(LIS\) int LIS(int *a, int n) { int *d = new int[n + 5]; int *g = new int[n + 5]; for(int i=1; i<=n; ++i) g[i] = INF; // INF = 2147483647 for(int i=1; i<=n; ++i) { int k = lower_bound(g+1, g+1+n, a[i]) - g; d[i] = k; g[k] =

动态规划刷题记录1(不定期更新~)

Dp刷(chao)题记录&题(fu)解(zhi) 1.bzoj1055 [HAOI2008]玩具取名 题目大意:字典中有四个字母,’w’\’i’\’n’\’g’,给出每个字母的转换关系,即某个单个字母可以转换为两个字母.给出一个文本,求最初的可能文本(刚开始有且仅有一个字母). 题解:明显是一道区间dp嘛~.设状态为文本[i,j]内的字母可以转化为字母[k],即f(i,j,k),要解状态的可能性.转移思路,自然是枚举i到j内的断点,再枚举关系.那么初始的状态转移方程就是 f[i][j][k]=f

[LeetCode] Unique Paths &amp;&amp; Unique Paths II &amp;&amp; Minimum Path Sum (动态规划之 Matrix DP )

Unique Paths https://oj.leetcode.com/problems/unique-paths/ A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to rea

LeetCode总结 -- 一维动态规划篇

这篇文章的主题是动态规划, 主要介绍LeetCode中一维动态规划的题目, 列表如下: Climbing Stairs Decode Ways Unique Binary Search Trees Maximum Subarray Maximum Product Subarray Best Time to Buy and Sell Stock 在介绍上述具体题目之前, 我们先说说动态规划的通常思路. 动态规划是一种算法思路(注意这里不要和递归混淆, 事实上递归和迭代只是两种不同的实现方法, 并不