4527: K-D-Sequence

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 163  Solved: 66
[Submit][Status][Discuss]

Description

我们称一个数列为一个好的k-d数列,当且仅当我们在其中加上最多k个
数之后,数列排序后为一个公差为d的等差数列。
你手上有一个由n个整数组成的数列a。你的任务是找到它的最长连续子
串,使得满足子串为好的k-d数列。

Input

第一行包含三个用空格隔开的整数n,k,d(1<=n<=2*10^5;0<=k<=
2*10^5;0<=d<=10^9)。第二行包含n个空格隔开的整数:a1,a2,...,an(-10^9<=ai<=10^9)表示数列a。

Output

输出两个用空格隔开的整数L,r(1<=L<=r<=n),表示数列a_L,a_L+1,...,
ar是好k-d数列的子串中最长的。
如果有多个最优答案,输出那个L值最小的。
 

Sample Input

6 1 2
4 3 2 8 6 2

Sample Output

3 5
//第一个测试样例的答案为包括数字 2,8,6 的子串——在加入数字 4 并且
排序之后,它变成了数列 2,4,6,8——公差为 2 的等差数列。

HINT

Source

分析:

考虑如果一个数列可以成为等差数列,其必要条件是任意$a[i]$%$d$都是相等的,也就是说,我们要找出连续的最长一段同余子串,使得其满足可以成为等差数列...

接的我们发现,可以把公差为$d$转化为公差为$1$,也就是满足$max(\frac{a[i]}{d})-min(\frac{a[i]}{d})+1-(j-i+1)<=k$,感觉还是很好理解的...

所以我们考虑枚举子串的右端点,然后找到最靠左的满足要求的点,发现我们可以用线段树来维护信息,维护三个值,$Min$代表的是最小的$min+l$,$Max$代表的是最小的$max+l$,$Sum$代表的是最小的$min+max+l$,然后我们每把右端点右移一位,就把当前的点影响的区间修改...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
#define inf 2e9+7
using namespace std; const int maxn=200000+5; int n,k,d,top,ans,ansl,ansr,a[maxn],b[maxn],c[maxn],pre[maxn],stk[maxn],lmax[maxn],lmin[maxn]; map<int,int> mp; struct M{ int l,r;
long long Min,Max,Sum,tagMax,tagMin; inline void init(void){
Min=Max=Sum=tagMin=tagMax=inf;
} }tree[maxn<<2]; inline void pushdown(int tr,int l,int r,int mid){
int val;
if(tree[tr].tagMax!=inf)
val=tree[tr].tagMax,
tree[tr<<1].Max=val+l,
tree[tr<<1].tagMax=val,
tree[tr<<1].Sum=val+tree[tr<<1].Min,
tree[tr<<1|1].Max=val+mid+1,
tree[tr<<1|1].tagMax=val,
tree[tr<<1|1].Sum=val+tree[tr<<1|1].Min,
tree[tr].tagMax=inf;
if(tree[tr].tagMin!=inf)
val=tree[tr].tagMin,
tree[tr<<1].tagMin=val,
tree[tr<<1].Min=-val+l,
tree[tr<<1].Sum=-val+tree[tr<<1].Max,
tree[tr<<1|1].tagMin=val,
tree[tr<<1|1].Min=-val+mid+1,
tree[tr<<1|1].Sum=-val+tree[tr<<1|1].Max,
tree[tr].tagMin=inf;
} inline void update(int tr){
tree[tr].Min=min(tree[tr<<1].Min,tree[tr<<1|1].Min);
tree[tr].Max=min(tree[tr<<1].Max,tree[tr<<1|1].Max);
tree[tr].Sum=min(tree[tr<<1].Sum,tree[tr<<1|1].Sum);
} inline void build(int l,int r,int tr){
tree[tr].l=l,tree[tr].r=r,tree[tr].init();
if(l==r){
tree[tr].Max=c[l]+l,tree[tr].Min=-c[l]+l,tree[tr].Sum=l;
return;
}
int mid=(l+r)>>1;
build(l,mid,tr<<1);build(mid+1,r,tr<<1|1);
update(tr);
} inline void change(int l,int r,int id,int val,int tr){
if(tree[tr].l==l&&tree[tr].r==r){
if(id==0) tree[tr].tagMax=val,tree[tr].Max=val+tree[tr].l,tree[tr].Sum=tree[tr].Min+val;
if(id==1) tree[tr].tagMin=val,tree[tr].Min=-val+tree[tr].l,tree[tr].Sum=tree[tr].Max-val;
return;
}
int mid=(tree[tr].l+tree[tr].r)>>1;
pushdown(tr,tree[tr].l,tree[tr].r,mid);
if(r<=mid)
change(l,r,id,val,tr<<1);
else if(l>mid)
change(l,r,id,val,tr<<1|1);
else
change(l,mid,id,val,tr<<1),change(mid+1,r,id,val,tr<<1|1);
update(tr);
} inline int find(int tr,int val){
if(tree[tr].Sum>val) return n+1;
if(tree[tr].l==tree[tr].r) return tree[tr].l;
pushdown(tr,tree[tr].l,tree[tr].r,tree[tr].l+tree[tr].r>>1);
if(val>=tree[tr<<1].Sum) return find(tr<<1,val);
return find(tr<<1|1,val);
} inline int query(int l,int r,int tr,int val){
if(tree[tr].l==l&&tree[tr].r==r) return find(tr,val);
int mid=(tree[tr].l+tree[tr].r)>>1;
pushdown(tr,tree[tr].l,tree[tr].r,mid);
if(r<=mid) return query(l,r,tr<<1,val);
else if(l>mid) return query(l,r,tr<<1|1,val);
else{
int lala=query(l,mid,tr<<1,val);
if(lala==n+1)
return query(mid+1,r,tr<<1|1,val);
return lala;
}
} inline void solve(void){
for(int i=1,j;i<=n;i=j+1){
for(j=i;j<n&&a[j]==a[j+1];j++);
if(j-i+1>ans) ans=j-i+1,ansl=i,ansr=j;
}
printf("%d %d\n",ansl,ansr);
} signed main(void){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d%d%d",&n,&k,&d);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) a[i]+=1e9;ans=ansl=ansr=1;
if(d==0) return solve(),0;
for(int i=1;i<=n;i++){
if(mp.find(a[i])==mp.end()) mp[a[i]]=i,pre[i]=0;
else pre[i]=mp[a[i]],mp[a[i]]=i;
}
for(int i=1;i<=n;i++) b[i]=a[i]%d,c[i]=a[i]/d;
build(1,n,1);
for(int i=n;i>=1;i--){
while(top&&c[stk[top]]>=c[i]) lmin[stk[top--]]=i;
stk[++top]=i;
}
while(top) lmin[stk[top--]]=0;
for(int i=n;i>=1;i--){
while(top&&c[stk[top]]<=c[i]) lmax[stk[top--]]=i;
stk[++top]=i;
}
while(top) lmax[stk[top--]]=0;
for(int i=1,j;i<=n;i=j+1){
for(j=i;j<n&&b[j]==b[j+1];j++);
for(int t=i,tmp;t<=j;t++){
if(pre[t]>=i){
j=pre[t];
break;
}
change(max(i,lmax[t]+1),t,0,c[t],1),
change(max(i,lmin[t]+1),t,1,c[t],1);
tmp=query(i,t,1,k+t);
if(t-tmp+1>ans) ans=t-tmp+1,ansl=tmp,ansr=t;
}
}
printf("%d %d\n",ansl,ansr);
return 0;
}

  


By NeighThorn

BZOJ 4527: K-D-Sequence的更多相关文章

  1. [bzoj P4504] K个串

    [bzoj P4504] K个串 [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次 ...

  2. BZOJ 3110 K大数查询 | 整体二分

    BZOJ 3110 K大数查询 题面 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个 ...

  3. 【BZOJ 4527】 4527: K-D-Sequence (线段树)

    4527: K-D-Sequence Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 145  Solved: 59 Description 我们称一个 ...

  4. BZOJ 3110 k大数查询 & 树套树

    题意: 有n个位置,每个位置可以看做一个集合,现在要求你实现一个数据结构支持以下功能: 1:在a-b的集合中插入一个数 2:询问a-b集合中所有元素的第k大. SOL: 调得火大! 李建说数据结构题能 ...

  5. [BZOJ]3110 K大数查询(ZJOI2013)

    这大概是唯一一道小C重写了4次的题目. 姿势不对的树套树(Fail) → 分块(Fail) → 整体二分(Succeed) → 树套树(Succeed). 让小C写点心得静静. Description ...

  6. bzoj : 4504: K个串 区间修改主席树

    4504: K个串 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 268  Solved: 110[Submit][Status][Discuss] ...

  7. BZOJ - 4520 K远点对

    题意:已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对 维护大小为2k最小堆,KD树的估值用前面提到的做法 PS.网上有人估价是使用边界四个点的最值来独立枚举,然而这样写似乎过不了 #incl ...

  8. bzoj 1005 组合数学 Purfer Sequence

    这题需要了解一种数列: Purfer Sequence 我们知道,一棵树可以用括号序列来表示,但是,一棵顶点标号(1~n)的树,还可以用一个叫做 Purfer Sequence 的数列表示 一个含有 ...

  9. bzoj 2656 [Zjoi2012]数列(sequence) 递推+高精度

    2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Descri ...

随机推荐

  1. Hbase表格设计

    Rowkey设计 Region: 基于RowKey的分区,可理解成MySQL的水平切分. 每个Region Server就是Hadoop集群中一台机器上的一个进程. 比如我们的有1-300号的RowK ...

  2. **leetcode笔记--4 Sum of Two Integers

    question: Calculate the sum of two integers a and b, but you are not allowed to use the operator + a ...

  3. 云计算之路-阿里云上:奇怪的CPU 100%问题

    这篇博文记录一下6月1日在阿里云上遇到的奇怪的CPU 100%问题,希望多年以后能真相大白. 那天负载均衡(SLB)中只放了1台云服务器(平时都放2台),由于是节假日,虽然只放了一台,但这台服务器的负 ...

  4. VS2013生产过程问题及解决

    TRK0002错误 现象:编译器.链接器交替报错,不能正常生成 环境:Win8.1 + VS2013 + 百度杀毒 解决:退出百度杀毒,重启VS,再进行生成 修订:发现问题依旧,经过多次试验,发现与杀 ...

  5. ExtJs4.1目录结构介绍和使用说明[转]

    一.在做ExtJs开发之前首先要到网站上下载ExtJs的开发包,我用的最新版本是4.1.1.此版本相对于之前的版本目录结构发生了一些变化,没有了adapter目录, 目录结构如下 文件/文件夹名的作用 ...

  6. svn资源库url问题

    今天连接svn资源库的时候一直出现 RA layer request failedsvn: Unable to connect to a repository at URL http://... sv ...

  7. 第十五篇 Python之文件处理

    一 文件操作  介绍 计算机系统分为:计算机硬件,操作系统,应用程序三部分. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所 ...

  8. GFS文件系统

      1.1 分布式文件系统 1.1.1 什么是分布式文件系统 相对于本机端的文件系统而言,分布式文件系统(英语:Distributed file system, DFS),或是网络文件系统(英语:Ne ...

  9. C++ 学习笔记之——输入和输出

    在 C++ 中,我们通过调用输入输出流库中的流对象 cin 和 cout 来实现输入和输出. #include <iostream> using namespace std; int ma ...

  10. VC中结构体的内存布局

    看了 VC++中内存对齐 这篇文章,感觉说复杂了,根据我的总结,要算出结构体的内存大小和偏移量,只要清楚结构体各成员的内存布局就行了,下面介绍一下我总结的规则,有不对之处,欢迎回复. 1.实际PACK ...