线段树专题-等差子序列

感谢

感谢孙耀峰的线段树PPT,使我获益匪浅.

题目来源

BZOJ−2124BZOJ-2124BZOJ−2124

题意

给出长度为nnn的1−n1-n1−n的排列AAA
问是否存在一组1≤p1≤p2≤...≤pl≤n,l≥31 \le p_1 \le p_2 \le ... \le p_l \le n,l \ge 31≤p1​≤p2​≤...≤pl​≤n,l≥3
使得Ap1,Ap2,...,AplA_{p1},A_{p2},...,A_{pl}Ap1​,Ap2​,...,Apl​构成等差序列
数据范围n≤104n \le 10^4n≤104

题解

只要能形成长度为333的等差子序列,就直接输出YesYesYes即可.

即需要寻找i,j,ki,j,ki,j,k满足Ai=Aj−t,Ak=Aj+t,且t>0.A_i = A_j - t,A_k = A_j + t,且t > 0.Ai​=Aj​−t,Ak​=Aj​+t,且t>0.

根据转化后的式子,我们只需要枚举jjj,判断是否存在这样的ttt即可.

考虑到AAA是一个排列,排列中的数两两不同,因此我们可以考虑开一个数据结构维护一下内容:

当枚举到AjA_jAj​的时候,我可以很快的查询任何一个AiA_iAi​在AjA_jAj​的左边还是右边,(记如果i&lt;ji&lt;ji<j则AjA_jAj​应该标记为000表示在左边,若i&gt;ji&gt;ji>j则AjA_jAj​应该标记为111表示在右边).

这样的话,如果010101串[Aj−t,Aj−1][A_j-t,A_j-1][Aj​−t,Aj​−1]与[Aj+1,Aj+t][A_j+1,A_j+t][Aj​+1,Aj​+t]之间有一位不相同(也就是说存在关于AjA_jAj​的对称位置的两个数在AjA_jAj​两侧,说明可以形成等差子序列).

因此只有当以上两个01串,翻转过来完全相同的情况下,才不存在以AjA_jAj​作为中心的等差序列.

如何判断010101串相同呢?答案是哈希.

建立一颗线段树,维护的是010101串的正向和反向哈希值.

从小到大枚举Aj,[1,n]A_j,[1,n]Aj​,[1,n],然后更新线段树,并判断是否有以AjA_jAj​为对称中心的等差序列.

代码

#include <iostream>
#include <cstring>
const int N = 10007;
typedef unsigned long long ull;
int T,n;
int a[N];ull pow[N];
struct work{ull hash0,hash1;int len;
};#define pr(x) std::cout << #x << ": " << x << std::endl
struct segtree{ull hashs[N * 4][2];void maintain(int rt,int l,int r) {int mid = (l + r) / 2;hashs[rt][0] = hashs[rt*2][0] + hashs[rt*2+1][0] * pow[mid - l + 1];hashs[rt][1] = hashs[rt*2+1][1] + hashs[rt*2][1] * pow[r - mid];}void change(int rt,int l,int r,int pos,int val) {if(l == r) {hashs[rt][0] = hashs[rt][1] = val;return ;}   int mid = (l + r) / 2;if(pos > mid) change(rt*2+1,mid+1,r,pos,val);elsechange(rt*2,l,mid,pos,val);maintain(rt,l,r);}work query(int rt,int l,int r,int ql,int qr) {if(r < ql || qr < l) {return (work){0,0,0};} else if(ql <= l && r <= qr) {return (work){hashs[rt][0],hashs[rt][1],r - l + 1};}int mid = (l + r) / 2;work wa = query(rt*2,l,mid,ql,qr);work wb = query(rt*2+1,mid+1,r,ql,qr);return (work){wa.hash0 + wb.hash0 * pow[wa.len],wb.hash1 + wa.hash1 * pow[wb.len],wa.len + wb.len};}}seg;int main()
{pow[0] = 1;for(int i = 1;i < N;++i) pow[i] = 3 * pow[i-1];std::ios::sync_with_stdio(false);std::cin >> T;while(T--) {int f = 0;memset(&seg,0,sizeof(seg));std::cin >> n;for(int i = 1;i <= n;++i) {std::cin >> a[i];seg.change(1,1,n,a[i],1);if(a[i] == 1 || a[i] == n) continue;int len = std::min(a[i]-1,n - a[i]);work wa = seg.query(1,1,n,a[i]-len,a[i]-1);work wb = seg.query(1,1,n,a[i]+1,a[i]+len);if(wa.hash0 != wb.hash1) {f = 1;}}if(!f) std::cout << "N" << std::endl;elsestd::cout << "Y" << std::endl;}return 0;
}

线段树专题-等差子序列 BZOJ-2124相关推荐

  1. 线段树专题-黑白棋盘 BZOJ-1453

    线段树专题-黑白棋盘 题目来源 BZOJ−1453BZOJ-1453BZOJ−1453 题意 QQQ次操作 每次操作给出(x,y)(x,y)(x,y),将(x,y)(x,y)(x,y)个格子颜色取反 ...

  2. 2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)

    P4198 楼房重建 线段树维护以某点为开头的最长不下降子序列 使用下面calc函数能够计算线段树u维护的区间中,以x为开头最长不下降子序列的个数. calc需要维护区间最值. template< ...

  3. 2018 UESTC 线段树专题

    A - 一棵简单的线段树 A[1...n]初始全为0. 1. 给两个数p 和 x(1≤p≤n),单点更新 A[p] <- x 2. 给两个数L和R (1≤L<R≤n),  L到R区间里这几 ...

  4. 蒟蒻君的刷题日记Day12(线段树专题T4):P8082 [COCI2011-2012#4] KEKS 线段树版题解

    解题思路 看题解区的大佬们用的都是单调栈,本蒟蒻献上一篇线段树题解. 整个数最大,首先位数是确定的,则肯定优先考虑高位大小. 大体思路就是从前向后依次求出每一位的值(好像是废话). 对于第 iii 位 ...

  5. 线段树专题 A(单点更新)

    #include <iostream> #include<cstdio> #include<cstring> using namespace std; const ...

  6. HDU 4417 Super Mario(线段树||树状数组+离线操作 之线段树篇)

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

  7. 【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

    [POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  8. 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

    [BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...

  9. 【BZOJ4991】我也不知道题目名字是什么(线段树)

    [BZOJ4991]我也不知道题目名字是什么(线段树) 题面 BZOJ 题解 对于线段树维护的区间维护以下东西: 区间左(右)端开始(结束)的最长(短)子串的长度 左端右端的值,以及当前区间内的答案 ...

最新文章

  1. 关于Exception类
  2. 在 Docker 上运行一个 RESTful 风格的微服务
  3. 执行计划oracle中cost,执行计划中cost计算方法
  4. SparkSql之DataFrame操作
  5. Target runtime com.genuitec.runtime.generic.jee60 is not defined
  6. Content Delivery Network (CDN)
  7. 机器学习算法篇:最大似然估计证明最小二乘法合理性
  8. STM32F1系列简单介绍及入门学习
  9. python复数类型-Python 复数属性和方法操作实例
  10. LVDS 扫盲基础知识
  11. 【时光纪念】我,留在2015的时光
  12. [暑假的bzoj刷水记录]
  13. 自再现模形成过程matlab,激光原理课程设计--平行平面腔自再现模Fox-Li数值迭代解法及MATLAB实现.doc...
  14. 小白建网站,该如何入手?
  15. 详解宏定义(#define)【转】
  16. 如何在Java面试中克服恐惧?
  17. 指甲上长 黑线  ,出问题的可能是: 肾/肝/肠胃/皮肤。需要去医院,看皮肤科和 消化科。
  18. tkmbatis 日志_springboot+maven+tk.mybatis+generator逆向工程
  19. Vue项目覆盖率展示
  20. 后渗透(内网渗透学习笔记)

热门文章

  1. oracle leg函数,032-函数的嵌套与LEGB原则
  2. linux磁盘写保护怎么修改_mount: /dev/vdb 写保护,将以只读方式挂载
  3. 服务器虚拟化分为半,服务器虚拟化有哪些?
  4. 蓝桥杯-代码-数字三角形
  5. [Java基础]字符流中的编码解码问题
  6. 二叉树的中序遍历非递归方法(算法导论第三版12.1-3)
  7. Board Moves CodeForces - 1353C(数学)
  8. Hystrix在网关Zuul使用中遇到问题
  9. 蓝桥杯 递增三元组 二分
  10. P2408 不同子串个数 SAM