[CF407E]k-d-sequence
题意:给定$a_{1\cdots n}$,让你求出一个最长的子串$a_{l\cdots r}$,使得这个子串加上最多$k$个数字并排序后是一个公差为$d$的等差数列
首先$d=0$就是最长连续相等段,扫一遍解决
然后显然$a_{l\cdots r}$都是模$d$同余的,我们不妨对模$d$的余数不同的段分开处理
把每个数先$+10^9$(让它变为非负)再除以$d$,转化为$d=1$的问题
那么题目的限制条件就是$\mathop\max\limits_{i=l}^ra_i-\mathop\min\limits_{i=l}^ra_i+1\leq r-l+1+k$且$a_{l\cdots r}$中没有重复元素
所以整个算法的大致思路就是,对$a_{l\cdots r}$,从大到小枚举$i\in[l,r]$,找到最大的$j\in[l,r]$满足$\mathop\max\limits_{k=i}^ja_k-\mathop\min\limits_{k=i}^ja_k-r\leq k-l$且$a_{i\cdots j}$中没有相同元素
没有相同元素:直接用一个map存每个数上一次出现的位置,相应左移$r$即可
对于这个不等式,注意到$f(r)=\mathop\max\limits_{i=l}^ra_i$是单调不减的,所以我们可以用一个单调栈存当前区间内对于不同的$j$,对上式有贡献的$a_i$(即从左往右扫,会令当前最大值变化的那些$a_i$),$\min$同理,当左端点移动时,入栈出栈的同时用线段树维护$\max-\min$即可,对于$-r$,建线段树时第$i$位的初值赋为$-i$即可,我们只需要在线段树上二分找到最右的$\leq k-i$的值即可
#include<stdio.h> #include<map> using namespace std; int mn[800010],ad[800010]; void add(int x,int v){ mn[x]+=v; ad[x]+=v; } void pushdown(int x){ if(ad[x]){ add(x<<1,ad[x]); add(x<<1|1,ad[x]); ad[x]=0; } } void pushup(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);} void build(int l,int r,int x){ if(l==r){ mn[x]=-l; return; } int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); pushup(x); } void modify(int L,int R,int v,int l,int r,int x){ if(L<=l&&r<=R)return add(x,v); pushdown(x); int mid=(l+r)>>1; if(L<=mid)modify(L,R,v,l,mid,x<<1); if(mid<R)modify(L,R,v,mid+1,r,x<<1|1); pushup(x); } int query(int L,int R,int v,int l,int r,int x){ if(mn[x]>v)return 0; if(l==r)return l; pushdown(x); int mid=(l+r)>>1,res; if(R>mid){ res=query(L,R,v,mid+1,r,x<<1|1); if(res)return res; } if(L<mid){ res=query(L,R,v,l,mid,x<<1); if(res)return res; } return 0; } map<int,int>pos; int a[200010],s1[200010],s2[200010],n,k,d,t1,t2,L,R; void solve(int l,int r){ if(l==r)return; int i,tr,res; for(i=l;i<=r;i++)a[i]=a[i]/d+1; tr=r+1; pos.clear(); t1=t2=0; s1[0]=s2[0]=r+1; for(i=r;i>=l;i--){ if(pos.count(a[i]))tr=min(tr,pos[a[i]]); while(t1&&a[i]>a[s1[t1]]){ modify(s1[t1],s1[t1-1]-1,-a[s1[t1]],1,n,1); t1--; } t1++; s1[t1]=i; modify(s1[t1],s1[t1-1]-1,a[i],1,n,1); while(t2&&a[i]<a[s2[t2]]){ modify(s2[t2],s2[t2-1]-1,a[s2[t2]],1,n,1); t2--; } t2++; s2[t2]=i; modify(s2[t2],s2[t2-1]-1,-a[i],1,n,1); res=query(i,tr-1,k-i,1,n,1); if(res-i>R-L||(res-i==R-L&&i<L)){ L=i; R=res; } pos[a[i]]=i; } } int main(){ int i,l,r; scanf("%d%d%d",&n,&k,&d); for(i=1;i<=n;i++){ scanf("%d",a+i); a[i]+=1000000000; } L=R=1; if(d==0){ for(l=1;l<=n;l=r){ for(r=l;r<=n&&a[r]==a[l];r++); if(r-l>R-L+1){ L=l; R=r-1; } } printf("%d %d",L,R); return 0; } build(1,n,1); L=R=1; for(l=1;l<=n;l=r){ for(r=l;r<=n&&a[l]%d==a[r]%d;r++); solve(l,r-1); } printf("%d %d",L,R); }
[CF407E]k-d-sequence的更多相关文章
- 【dfs】Sequence Decoding
Sequence Decoding 题目描述 The amino acids in proteins are classified into two types of elements, hydrop ...
- Gym 100703G---Game of numbers(DP)
题目链接 http://vjudge.net/contest/132391#problem/G Description standard input/outputStatements — It' s ...
- 转:Python获取随机数(中文)
下面介绍下random中常见的函数. 前提:需要导入random模块 >>>import random 1.random.random random.random() 用于生成一个0 ...
- Qt4--加密日记本(子例化QMainWindow文本加密解密)
近来刚学习Qt4编程,想找个实例练习练习,于是产生了一个想法,就是怎么样做一个文本加密,这样,自己保存的一些文档可以通过软件 生成加密文本,到时候要看的时候,通过自己的软件读取就可以.既然有想法了,那 ...
- python随机数
前提:需要导入random模块 >>>import random 1.random.random random.random()用于生成一个0到1的随机符小数: 0 <= n ...
- 关于python 模块导入
如何将自己写的库加入到python的库路径中: 首先查看python包含的库路径,步骤如下: a.打开python命令界面 b.import sys c.sys.path 1.在python安 ...
- 剑指Offer 23. 二叉搜索树的后序遍历序列 (二叉搜索树)
题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 题目地址 https://www.nowcoder ...
- 开发笔记:python与随机数(转)
这些天需要用到从一堆数中随机提取几个数,于是重新研究了下random模块. 下面介绍下random中常见的函数. 前提:需要导入random模块 >>>import random 1 ...
- Leetcode 413. Arithmetic Slice 算术序列切片(动态规划,暴力)
Leetcode 413. Arithmetic Slice 算术序列切片(动态规划,暴力) 题目描述 如果一个数组1.至少三个元素2.两两之间差值相同,那么这个数组就是算术序列 比如下面的数组都是算 ...
- python随机数的产生
导入 random模块 >>> import random 1. random.random random.random()用于生成一个0到1的随机浮点数: 0 <= n ...
随机推荐
- wyh的天鹅~vector的使用
链接:https://www.nowcoder.com/acm/contest/93/L来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 使用babel把es6代码转成es5代码
第一步:创建一个web项目 使用命令:npm init 这个命令的目的是生成package.json. 执行第二步中的命令后生成的package.json的文件的内容是: { "name&q ...
- 记录一发wm_concat()函数排序的问题
需求:需要将列转行之后的工序按照待执行工序号排序,如果一样按工序号排 解决方法如下: select part_no, max(ywggx) ywggx from(select mt.part_no , ...
- c++ fstream用法(2)
一> #include "stdafx.h" #include<iostream> #include<string> #include<fstr ...
- jaspersoft中分组打印
一:前言 使用IReport已经四个月了,最近在做一个保镖,是要按照类型分类,并且这些类型要横着打印,最后还要算这个类型金额的总值,这张报表现是说需要用到子报表,最后和一个同事一起用group来分组做 ...
- 【Foreign】最大割 [线性基]
最大割 Time Limit: 15 Sec Memory Limit: 256 MB Description Input Output Sample Input 3 6 1 2 1 1 2 1 3 ...
- django中管理程序2
升级版 from os import path TASKS_ROOT = path.dirname(path.abspath(path.dirname(__file__))) PYTHON_ROOT ...
- passwd讲解
root:$dffjioowwf/:16274:0:999999:7::: 1用户名:密码:最近修改密码的日期:密码不能更改的天数:密码过期时间:密码需要更改期限到拉前7发出警告:宽限天数:帐号过期时 ...
- Buildroot自动化交叉编译工具:其一【转】
转自:http://blog.csdn.net/youyudehexie/article/details/7583657 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] Bui ...
- cpu_relax( )-----对自选循环等待(spin-wait loops)操作的优化【转】
cpu_relax()-----对自选循环等待(spin-wait loops)操作的优化 转自:http://www.doc100.net/bugs/t/173547/index.html 在loc ...