文章目录

  • CF407 E. k-d-sequence
    • problem
    • solution
    • code

CF407 E. k-d-sequence

problem

solution

  • special case,d=0d=0d=0,相当于寻找最长的一段数字相同的区间

  • other case,如果要满足公差为ddd等差序列

    • 区间内每个数在模ddd意义下同余
    • 每个数互不相同
  • 算法流程

    • 先将序列分成若干个同余mmm的子区间,从左往右扫一遍,即可得到

    • 对于同余的子区间,把所有数进行x−rd\frac{x-r}{d}dx−r​的操作,转化为求公差为111的等差数列

    • 对于区间[l,r][l,r][l,r],需要增加的个数max⁡{xi∣l≤i≤r}−min⁡{xi∣l≤i≤r}+1−(r−l+1)\max\{x_i|l\le i\le r\}-\min\{x_i|l\le i\le r\}+1-(r-l+1)max{xi​∣l≤i≤r}−min{xi​∣l≤i≤r}+1−(r−l+1)

      满足增加个数≤k\le k≤k

    • 从小到大顺次枚举rrr,那么就是要最小化lll

      • [l,r][l,r][l,r]区间不重复

        可以通过map快速查到与xrx_rxr​值相同的点的位置,假设为pospospos

        则需满足pos<lpos<lpos<l

      • 加的数个数不能超过kkk

        max⁡{xi∣l≤i≤r}−min⁡{xi∣l≤i≤r}+1−(r−l+1)≤k\max\{x_i|l\le i\le r\}-\min\{x_i|l\le i\le r\}+1-(r-l+1)\le kmax{xi​∣l≤i≤r}−min{xi​∣l≤i≤r}+1−(r−l+1)≤k

        ⇕\Updownarrow⇕

        max⁡{xi∣l≤i≤r}−min⁡{xi∣l≤i≤r}+l≤k+r\max\{x_i|l\le i\le r\}-\min\{x_i|l\le i\le r\}+l\le k+rmax{xi​∣l≤i≤r}−min{xi​∣l≤i≤r}+l≤k+r

        用线段数维护wl=max⁡{xi∣l≤i≤r}−min⁡{xi∣l≤i≤r}+lw_l=\max\{x_i|l\le i\le r\}-\min\{x_i|l\le i\le r\}+lwl​=max{xi​∣l≤i≤r}−min{xi​∣l≤i≤r}+l

        设lll的下界为pospospos,则要在[pos,r][pos,r][pos,r]找最左边的lll,满足wl≤k+rw_l\le k+rwl​≤k+r

  • 最后只剩下如何维护www

    单调栈,维护一个递增单调栈和一个递减单调栈。以递减为例

    递减单调栈当一个大于栈顶的元素加入时,会不断弹出栈顶,因此单调栈可以将max(L,R)max(L,R)max(L,R)分成递减的若干段

    单调栈中的一个点其实代表的是一个区间,弹栈顶相当于最大值变化

    被弹出的元素的线段树的最大值变化即是线段树上区间加

code

#include <map>
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define maxn 200005
map < int, int > last;
int n, k, d, pos, flag, ans_l = 1, ans_r = 1;
int a[maxn], Min[maxn], Max[maxn];
int t[maxn << 4], tag[maxn << 4];void build( int num, int l, int r ) {t[num] = l, tag[num] = 0;if( l == r ) return;int mid = ( l + r ) >> 1;build( num << 1, l, mid );build( num << 1 | 1, mid + 1, r );
}void pushdown( int num ) {t[num << 1] += tag[num];tag[num << 1] += tag[num];t[num << 1 | 1] += tag[num];tag[num << 1 | 1] += tag[num];tag[num] = 0;
}void modify( int num, int l, int r, int pos ) {pushdown( num );if( l == r ) {t[num] = 0;return;}int mid = ( l + r ) >> 1;if( pos <= mid ) modify( num << 1, l, mid, pos );else modify( num << 1 | 1, mid + 1, r, pos );t[num] = min( t[num << 1], t[num << 1 | 1] );
}void modify( int num, int l, int r, int L, int R, int w ) {if( R < l || r < L ) return; if( L <= l && r <= R ) {t[num] += w, tag[num] += w;return;}pushdown( num );int mid = ( l + r ) >> 1;modify( num << 1, l, mid, L, R, w );modify( num << 1 | 1, mid + 1, r, L, R, w );t[num] = min( t[num << 1], t[num << 1 | 1] );
}void find( int num, int l, int r, int k ) {if( l == r ) {pos = l, flag = 1;return;}pushdown( num );int mid = ( l + r ) >> 1;if( t[num << 1] <= k ) find( num << 1, l, mid, k );else find( num << 1 | 1, mid + 1, r, k );
}void query( int num, int l, int r, int L, int R, int k ) {if( flag || r < L || R < l ) return;if( L <= l && r <= R ) {if( t[num] <= k ) find( num, l, r, k );return;}pushdown( num );int mid = ( l + r ) >> 1;query( num << 1, l, mid, L, R, k );query( num << 1 | 1, mid + 1, r, L, R, k );
}signed main() {scanf( "%lld %lld %lld", &n, &k, &d );    for( int i = 1;i <= n;i ++ )scanf( "%lld", &a[i] );if( ! d ) {int l = 0, r = 0;for( int i = 1;i <= n;i ++ ) {if( a[i] != a[i - 1] ) l = r = i;else ++ r;if( r - l > ans_r - ans_l ) ans_r = r, ans_l = l;}return ! printf( "%lld %lld\n", ans_l, ans_r );}build( 1, 1, n );int min_top = 0, max_top = 0;for( int r = 1, l = 1;r <= n;r ++ ) {int t = l;if( ( a[r] - a[r - 1] ) % d ) l = r;//要求同余else l = max( l, last[a[r]] + 1 );//取max维护不重复的条件last[a[r]] = r;while( t < l ) modify( 1, 1, n, t ++ );//清除不属于[l,r]区间的所有线段树痕迹//Min:维护min{a[i]|l<=i<=r}的递增栈//Max:维护max{a[i]|l<=i<=r}的递减栈//栈内点管辖一个区间eg:s[top]管辖(s[top-1],s[top]] //w[l]=max[L,R]-min[L,R]+lwhile( min_top && Min[min_top] >= l && a[Min[min_top]] > a[r] ) {modify( 1, 1, n, Min[min_top - 1] + 1, Min[min_top], a[Min[min_top]] / d );//[L,R]中最小值变小 先把之前-min(L,R)的贡献抵消掉 所以是+min_top --;}//把现在真正的min(L,R)贡献放进去 所以是- modify( 1, 1, n, max( l, Min[min_top] + 1 ), r, -a[r] / d );Min[++ min_top] = r;while( max_top && Max[max_top] >= l && a[Max[max_top]] < a[r] ) {modify( 1, 1, n, Max[max_top - 1] + 1, Max[max_top], -a[Max[max_top]] / d );max_top --;}//取左端点max比较是保证单调栈中每个点管辖区间不重复且并集为整个大区间 modify( 1, 1, n, max( l, Max[max_top] + 1 ), r, a[r] / d );Max[++ max_top] = r;flag = 0, pos = 0;query( 1, 1, n, l, r, k + r );if( r - pos > ans_r - ans_l ) ans_l = pos, ans_r = r;}printf( "%lld %lld\n", ans_l, ans_r );return 0;
}

CF407 E. k-d-sequence(线段树+单调栈)相关推荐

  1. [Codeforces1132G]Greedy Subsequences——线段树+单调栈

    题目链接: Codeforces1132G 题目大意:给定一个序列$a$,定义它的最长贪心严格上升子序列为$b$满足若$a_{i}$在$b$中则$a_{i}$之后第一个比它大的也在$b$中.给出一个数 ...

  2. [线段树][单调栈] BZOJ 4527 CF 407E: K-D-Sequence

    SolutionSolution 可以把同余的串一起考虑,然后把所有数除以dd.变成公差为11的情况. 满足这样的条件 MAXL≤i≤RAi−MINL≤i≤RAi−R≤k−L MAX_{L\le i\ ...

  3. 【BZOJ-28921171】强袭作战大sz的游戏 权值线段树+单调队列+标记永久化+DP...

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MB Submit: 45  Solved: 30 [Submit][Status][Discuss] ...

  4. codeforces CF438D The Child and Sequence 线段树

    $ \Rightarrow $ 戳我进CF原题 D. The Child and Sequence time limit per test: 4 seconds memory limit per te ...

  5. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  6. 2019ICPC(南京) - Greedy Sequence(线段树)

    题目链接:点击查看 题目大意:题意不明(英语渣),网上的简洁版转化: 对于每个i,所在下标p[i],在[p[i]−k,p[i]+k]中找到小于i的最大数x,然后ans[i]=ans[x]+1即可. 题 ...

  7. Super Mario HDU - 4417(主席树解决区间数字小于k的个数||线段树+离线)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  8. P3714 [BJOI2017]树的难题(点分治/线段树/单调队列)

    P3714 [BJOI2017]树的难题 求解树上长度在L到R的树链中颜色段权值和最大的链. 首先求解树上链的问题,而且限制了链的长度,那么我们需要点分治处理,然后考虑每次分治,我们可以把链分成两类, ...

  9. CF #669 (Div. 2)D. Discrete Centrifugal Jumps(线段树/单调队列优化dp)

    https://codeforces.com/contest/1407/problem/D 题意:给定n个高度,当i<ji<ji<j且满足以下条件之一时,可以从iii跳到jjj: 问 ...

最新文章

  1. Ubuntu里面一些权限问题
  2. Linux下搭建DNS服务器
  3. 2017-3-19四校联考
  4. 用SmarterFox替换Internet Explorer的“加速器”
  5. 让计算机开口说话教学反思,小班语言教案及教学反思《我会说普通话》
  6. javaSE---一个小项目(ATM机)
  7. php 防止url输入,php防止伪造数据从地址栏URL提交的方法
  8. java int范围_Java之int及它的取值范围
  9. xposed 主动调用方法_操作方法:主动容量管理
  10. Android功能点(一)——判断网络是否真正连通
  11. TensorFlow-Serving的使用实战案例笔记(tf=1.4)
  12. C Primer Plus 第七章 第七题
  13. 统计通话次数和时间的软件_通话时间统计app下载-通话时间统计安卓版 v2.2.2 - 安下载...
  14. Android studio 下载安装
  15. SSM框架整合以及使用思路梳理
  16. 五笔输入法 快速入门 二小时基本了解五笔
  17. Access键盘快捷键大全(一)
  18. 马云有自己的银行,为什么还要贷款?
  19. 如何一键重装win7系统?重装win7系统详细教程
  20. 普源DSA1030-TG,9kHz-3GHz频谱分析仪

热门文章

  1. 女朋友掉水里,各类程序猿怎么救?
  2. 入门 | 机器学习第一课:决策树学习概述与实现
  3. mysql触发器 node_node.js中事件触发器events的使用
  4. php+转义实体字符,PHP针对HTML实体字符的转义函数
  5. abaqus质量缩放系数取值_ABAQUS/Explicit质量缩放(MASS SCALING)使用心得  [转simwe]...
  6. weblogic修改控制台ip_「Weblogic学习」Weblogic知识要点之JNDI/JTA编程开发
  7. sae 本地环境 mysql数据库_SAE本地环境与真实环境的差别
  8. 计算机科普小知识——U盘格式化
  9. java xml 追加,java – 如何将节点从xml文档追加到现有的xml文档
  10. mysql 变量 数据类型_浅谈mysql(二)数据类型