首先,容易得到判断一个子串为“good k-d sequence”的方法:

  • 子串中没有重复元素,且所有元素模d相等。
  • 记mx为除以d的最大值,mn为除以d的最小值,则\(mx-mn<=r-l+k\)。

然后,我们对于每一段极大的元素同模的子串,处理\(d=1\)的情况。

显然,我们需要枚举一个端点。这里,我们从大到小枚举左端点。(当然,从小到大枚举右端点也是可行的)

我们使用单调栈和线段树,可以维护每个位置\(mx-mn\)的值。然后,因为对于每一个位置,\(r\)是固定的,所以我们把\(r\)移到左边。即有不等式\(mx-mn-r<=k-l\)。

然后,我们需要确定最右边的\(mx-mn-r<=k-l\)的元素位置,这个线段树上二分就可以了。

最后还有两个细节:

  • 为避免出现重复元素,线段树上二分时有限制。
  • 特判\(d=0\)的情况。

时间复杂度\(O(nlogn)\)。

#include <bits/stdc++.h>
using namespace std;
const int BAS = 1e9, N = 200010;
struct node {
int mn,tag;
inline void operator += (int x) {
mn += x;
tag += x;
}
inline void reset() {
mn = tag = 0;
}
} t[N << 2];
void push_down(int x) {
t[x<<1] += t[x].tag;
t[x<<1|1] += t[x].tag;
t[x].tag = 0;
}
void push_up(int x) {
if (t[x].tag) push_down(x);
t[x].mn = min(t[x<<1].mn,t[x<<1|1].mn);
}
void modify(int x,int l,int r,int v,int lp,int rp) {
if (lp > r || rp < l) return;
if (lp >= l && rp <= r)
return (void)(t[x] += v);
int mid = (lp + rp) >> 1;
modify(x<<1,l,r,v,lp,mid);
modify(x<<1|1,l,r,v,mid+1,rp);
push_up(x);
}
int dfs(int x,int lim,int v,int lp,int rp) {
if (t[x].mn > v) return -1;
if (lp == rp) return lp;
push_down(x);
int mid = (lp + rp) >> 1;
if (t[x<<1|1].mn <= v && mid + 1 <= lim) {
int res = dfs(x<<1|1,lim,v,mid+1,rp);
if (~res) return res;
}
return dfs(x<<1,lim,v,lp,mid);
}
int n,k,d,arr[N],len;
map<int,int> mp;
int tmp[N];
struct data_sta {
int l,r,val;
inline bool operator < (const data_sta& x) const {
return val < x.val;
}
} st[2][N];
int top[2];
struct data_ans {
int l,r;
inline bool operator < (const data_ans& x) const {
return r - l + 1 != x.r - x.l + 1 ? \
r - l + 1 > x.r - x.l + 1 : l < x.l;
}
};
data_ans solve() {
mp.clear();
data_sta tp;
data_ans res = (data_ans) {len,-1};
int cur = len, rec;
top[0] = top[1] = 0;
for (int i = len ; i >= 1 ; -- i) {
if (mp[tmp[i]]) cur = min(cur,mp[tmp[i]] - 1);
mp[tmp[i]] = i;
tp = (data_sta) {i,i,tmp[i]};
while (top[0] && st[0][top[0]].val < tp.val) {
modify(1,st[0][top[0]].l,st[0][top[0]].r,-st[0][top[0]].val,1,len);
tp.r = st[0][top[0]--].r;
}
st[0][++top[0]] = tp;
modify(1,tp.l,tp.r,tp.val,1,len);
tp = (data_sta) {i,i,tmp[i]};
while (top[1] && st[1][top[1]].val > tp.val) {
modify(1,st[1][top[1]].l,st[1][top[1]].r,st[1][top[1]].val,1,len);
tp.r = st[1][top[1]--].r;
}
st[1][++top[1]] = tp;
modify(1,tp.l,tp.r,-tp.val,1,len);
modify(1,i,i,-i,1,len);
rec = dfs(1,cur,k - i,1,len);
if (~rec) res = min(res,(data_ans) {i,rec});
}
for (int i = 1 ; i <= (len << 2) ; ++ i)
t[i].reset();
return res;
}
int special_solve() {
int res = 0, p = -1;
for (int i = 1, j; i <= n ; i += j) {
j = 1;
while (arr[i+j] == arr[i] && i + j <= n) ++ j;
if (res < j) res = j, p = i;
}
printf("%d %d\n",p,p + res - 1);
return 0;
}
int main() {
scanf("%d%d%d",&n,&k,&d);
for (int i = 1 ; i <= n ; ++ i)
scanf("%d",&arr[i]), arr[i] += BAS ;
if (d == 0) return special_solve();
data_ans res = (data_ans) {1,1}, tp;
for (int i = 1, j ; i <= n ; i += j) {
j = 1;
while (arr[i+j] % d == arr[i] % d && i + j <= n)
++ j;
len = j;
for (int s = 0 ; s < j ; ++ s)
tmp[s+1] = arr[i+s] / d;
tp = solve();
tp.l += i-1, tp.r += i-1;
res = min(res,tp);
}
printf("%d %d\n",res.l,res.r);
return 0;
}

小结:这样一类题目大概就是要怼着式子简化问题。

【做题】CF239E. k-d-sequence——线段树的更多相关文章

  1. 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

  2. Wow! Such Sequence!(线段树4893)

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...

  3. HDU 6047 Maximum Sequence(线段树)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047 题目: Maximum Sequence Time Limit: 4000/2000 MS (J ...

  4. Codeforces 438D The Child and Sequence - 线段树

    At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at ...

  5. ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集

    正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...

  6. Codeforces 486E LIS of Sequence(线段树+LIS)

    题目链接:Codeforces 486E LIS of Sequence 题目大意:给定一个数组.如今要确定每一个位置上的数属于哪一种类型. 解题思路:先求出每一个位置选的情况下的最长LIS,由于開始 ...

  7. K - Japan(线段树)

    Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Jap ...

  8. 【BZOJ】3038: 上帝造题的七分钟2(线段树+暴力)

    http://www.lydsy.com:808/JudgeOnline/problem.php?id=3038 这题我就有得吐槽了,先是线段树更新写错,然后不知哪没pushup导致te,精度问题sq ...

  9. 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 ...

  10. codevs2492上帝造题的七分钟 2(线段树)

    /* 区间修改 区间查询 可以用线段树搞 但是一般的标记下放对这个题好像不合适 只能改叶子 然后更新父亲(虽然跑的有点慢) 小优化:如果某个点是1 就不用再开方了 所以搞一个f[i]标记 i 这个点还 ...

随机推荐

  1. 六 js函数和this

    js的所有代码都是由funtion组成,funtion即函数的类型. 一.函数有两种写法 -----1.定义式 function test() { //定义一个函数 console.log(" ...

  2. 强化学习---TRPO/DPPO/PPO/PPO2

    时间线: OpenAI 发表的 Trust Region Policy Optimization, Google DeepMind 看过 OpenAI 关于 TRPO后, 2017年7月7号,抢在 O ...

  3. c扩展开发

    为什么要用C扩展 C是静态编译的,执行效率比PHP代码高很多.同样的运算代码,使用C来开发,性能会比PHP要提升数百倍.IO操作如CURL,因为耗时主要在IOWait上,C扩展没有明显优势. 另外C扩 ...

  4. keras如何求分类问题中的准确率和召回率

    https://www.zhihu.com/question/53294625 由于要用keras做一个多分类的问题,评价标准采用precision,recall,和f1_score:但是keras中 ...

  5. web基础,用html元素制作web页面

    用div,form制作登录页面,尽可能做得漂亮. 练习使用下拉列表选择框,无序列表,有序列表,定义列表. 观察常用网页的HTML元素,在实际的应用场景中,用已学的标签模仿制作. <!DOCTYP ...

  6. 随笔 js-----------------------------------------------------------------------------------------------------

    http://www.cnblogs.com/liuling/p/2014-4-19-04.html   redis Base64.encode($( "#byerName").v ...

  7. Python3自定义日志类 mylog

    #encoding=utf-8 import os, sysimport datetimeimport time class Mylog(object): # 根文件夹    root_dir = s ...

  8. Solr在Linux中的安装

    在Linux下进行安装: 我已经将压缩包放在了虚拟机下面了,然后开始进行解压缩. tar -zxvf solr-4.10.3.tar 解压完会多一个文件夹.在bin目录下会有这样的一个目录, 其中的这 ...

  9. m3u8文件下载合并的一种方法

    # -*- coding: utf-8 -*- """ Created on Wed Mar 14 15:09:14 2018 @author: Y "&quo ...

  10. MySQL修改库名的方法

    先创建新的库,再用RENAME TABLE 语句移动旧库中的表到新库,最后删除旧库. (root@localhost) [(none)] create database mydb_2; Query O ...