传送门——Luogu 传送门——Codeforces


如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列。可以枚举等差子序列的第二个元素\(b\),那么存在长度为\(3\)的等差子序列等价于:可以在\(b\)左边找到一个元素\(a\),在\(b\)右边找到一个元素\(c\),满足\(b - a = c - b\)。

对于找到\(ac\)两个元素,一个比较直观的想法是:对\(b\)左边和右边的所有元素各建一个bitset\(B1,B2\),对于某一个元素\(d \neq b\),如果\(d\)在\(b\)左边,那么\(B1[d]=1\),否则\(B2[d]=1\)。

不存在等差子序列意味着如果\(d\)在左边,则\(2 \times b - d\)一定不能在右边,反之同理。这等价于对于\([l,b-1](l \geq 1),[b + 1 , r](r \leq N)\),满足\(b - l = r - b\)时,有

\[B1[l,b-1] \lor rev(B2[b+1 , r]) = 2^{b - l} - 1\]

上面两个条件等价的原因是:若结果的第\(d\)位为\(0\),则\(B1[l,b-1]\)和\(rev(B2[b+1 , r])\)的第\(d\)位要么同时为\(0\),要么同时为\(1\)。若同时为\(0\)意味着\(b-d\)不在左边且\(b+d\)不在右边,同时为\(1\)意味着\(b-d\)在左边且\(b+d\)在右边,都存在等差子序列。如果其中有一个为\(0\),有一个为\(1\),\(b-d\)和\(b+d\)就会在同一边。

这样就可以从右往左枚举\(b\)的位置,动态维护\(B1,B2\)并查询。但是当数据范围到\(3 \times 10^5\)的时候bitset会TLE,这时可以使用Hash+树状数组维护与上面bitset意义相同的01串。复杂度变为\(O(nlogn)\)。

虽然CF是神机,但仍然需要注意常数。

//Luogu2757
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<cstring>
//This code is written by Itst
using namespace std;inline int read(){int a = 0;char c = getchar();while(!isdigit(c)) c = getchar();while(isdigit(c)){a = a * 10 + c - 48;c = getchar();}return a;
}#define st first
#define nd second
struct PII{int first , second;PII(int x = 0 , int y = 0):first(x) , second(y){}bool operator ==(PII a){return a.st == first && a.nd == second;}bool operator !=(PII a){return !(*this == a);}
};
const int MAXN = 1e4 + 7 , Base = 131 , MOD1 = 1e9 + 7 , MOD2 = 1e9 + 9;
PII powBs[MAXN] , sum[MAXN] , powInv[MAXN];
int arr[MAXN] , N , T;
bool f;PII operator *(PII a , PII b){return PII(1ll * a.st * b.st % MOD1 , 1ll * a.nd * b.nd % MOD2);
}PII operator +(PII a , PII b){PII t(a.st + b.st , a.nd + b.nd);if(t.st >= MOD1) t.st -= MOD1;if(t.nd >= MOD2) t.nd -= MOD2;return t;
}PII operator -(PII a , PII b){return a + PII(MOD1 - b.st , MOD2 - b.nd);}struct BIT{
#define lowbit(x) (x & -x)PII arr[MAXN];BIT(){memset(arr , 0 , sizeof(PII) * (N + 1));}void add(int pos , PII cur){while(pos <= N){arr[pos] = arr[pos] + cur;pos += lowbit(pos);}}PII get(int pos){PII sum = PII(0 , 0);while(pos){sum = sum + arr[pos];pos -= lowbit(pos);}return sum;}
}Tree1 , Tree2;inline int poww(long long a , int b , int MOD){int times = 1;while(b){if(b & 1) times = times * a % MOD;a = a * a % MOD;b >>= 1;}return times;
}void init(){powBs[0] = sum[0] = powInv[0] = PII(1 , 1);for(int i = 1 ; i <= 10000 ; ++i){powBs[i] = powBs[i - 1] * PII(Base , Base);sum[i] = sum[i - 1] + powBs[i];}powInv[1] = PII(poww(Base , MOD1 - 2 , MOD1) , poww(Base , MOD2 - 2 , MOD2));for(int i = 2 ; i <= 10000 ; ++i)powInv[i] = powInv[i - 1] * powInv[1];
}void work(){for(int i = 1 ; i <= N ; ++i)Tree1.add(arr[i] , powBs[arr[i]]);for(int i = N ; i ; --i){Tree1.add(arr[i] , PII(0 , 0) - powBs[arr[i]]);if(arr[i] != 1 && arr[i] != N){int l1 = 1 , r1 = arr[i] - 1 , l2 = arr[i] + 1 , r2 = N;if(r2 - l2 < r1 - l1) l1 = r1 - (r2 - l2);else r2 = l2 + (r1 - l1);PII t = (Tree1.get(r1) - Tree1.get(l1 - 1)) * powInv[l1] + (Tree2.get(N + 1 - l2) - Tree2.get(N - r2)) * powInv[N - r2 + 1];if(t != sum[r1 - l1]){f = 1;return;}}Tree2.add(N - arr[i] + 1 , powBs[N - arr[i] + 1]);}
}signed main(){
#ifndef ONLINE_JUDGEfreopen("in","r",stdin);//freopen("out","w",stdout);
#endifinit();for(int T = read() ; T ; --T){N = read();f = 0;for(int i = 1 ; i <= N ; ++i)arr[i] = read();Tree1 = BIT(); Tree2 = BIT();work();puts(f ? "Y" : "N");}return 0;
}

转载于:https://www.cnblogs.com/Itst/p/10629524.html

CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash相关推荐

  1. CF869 E. The Untended Antiquity 二位树状数组+hash

    题意 一个地图,然后三种操作  1.一个矩阵四周加上障碍  2.一个矩阵四周的障碍消除  3.问你两个点之间是否纯在一条路径不经过障碍 题解 我们可以给每一个矩阵一个hash值  然后将矩阵里面的点都 ...

  2. [luogu] P1637 三元上升子序列 树状数组

    前言 真简单,数据结构真简单!! 传送门 : 思路 计算一个 三元上升序列 我们可以枚举 中间节点 然后通过乘法原理 记录Left[]和Right[]Left[] 和 Right[]Left[]和Ri ...

  3. codeforces869EThe Untended Antiquity(二维树状数组)

    /* 二维树状数组+Hash 题意: 给一个地图(n,m) 三种操作: 1,在以(r1,c1).(r2,c2)为对角的矩形四条边上添加障碍 2,消除以(r1,c1).(r2,c2)为对角的矩形四条边上 ...

  4. 最长上升子序列(LIS)/最长不上升子序列问题算法详解+例题(树状数组/二分优化,看不懂你来打我)

    目录 最长上升子序列 一.朴素做法O(2n)O(2^n)O(2n) 二.优化做法O(nlogn)O(nlogn)O(nlogn) 三.例题引入:P1020 导弹拦截(求最长上升子序列和最长不上升子序列 ...

  5. 最长上升子序列三种模板(n^2模板,二分模板,树状数组模板)

    最长上升子序列(LIS)是动态规划的入门.总结下来,经常用的模板一共有三种,分别为n^2模板,二分模板,树状数组模板. n^2模板代码如下: //n^2算法,本质就是dp,采用二重循环的方式.对于数据 ...

  6. 【树状数组】递增子序列(金牌导航 数据结构优化DP-1)

    递增子序列 金牌导航 数据结构优化DP-1 题目大意 给出一个序列,让你求长度为m的单调递增子序列的个数 输入样例 3 2 1 1 2 7 3 1 7 3 5 9 4 8 输出样例 2 12 数据范围 ...

  7. bzoj 3173: [Tjoi2013]最长上升子序列(离线二分+树状数组)

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2051  Solved: 1041 [Submit] ...

  8. 求序列最长不下降子序列_树状数组解决最长不下降子序列 讲讲主要思路就好...

    展开全部 不降子序列求的是一个元素的值单调e69da5e887aa62616964757a686964616f31333361306430不降的序列. 传统的状态设计便是使用f[n] 表示到达第n位时 ...

  9. LIS最长上升子序列详解(动态规划、贪心+二分、树状数组)

    1.摘要: 关于LIS部分,本篇博客讲一下LIS的概念定义和理解,以及求LIS的三种方法,分别是O(n^2)的DP,O(nlogn)的二分+贪心法,以及O(nlogn)的树状数组优化的DP,最后附上几 ...

最新文章

  1. MATLAB实战系列(十二)-如何用人工鱼群算法解决带时间窗车辆路径(CVRP)问题(附MATLAB代码)
  2. 我要人人都看到我,但不知道我是谁
  3. 星之卡比镜之迷宫机器人_机器人工程师入门(0)
  4. Red Hat 6.0 Installation Steps
  5. 输入文字加下划线_微信昵称这样设置,文字加上下划线!
  6. 卡尔曼滤波 -- 从推导到应用(二)
  7. poj 3304 Segments
  8. 从SAP BPC中Entity维设计的理念考虑Web程序中类似文档库之类的设计该考虑的东西...
  9. openstack service glance-api/registry mysql of max_connection
  10. html五星评分标准,五星级酒店评分标准.doc
  11. 玩客云宝塔面板安装到外接硬盘
  12. cat6 万兆_干货:CAT5E超五类、CAT6和CAT6A超六类布线系统性能和应用上的区别
  13. lol8月7号服务器维护,LOL8月7日更新了什么内容 8.15新版本更新维护公告
  14. SOLID原理的详细信息。
  15. 如何提高团队管理能力?
  16. 笔记本安装固态涉及到的注意事项
  17. UCOS/UCOSII基础知识
  18. iowait 过高问题的查找及解决linux
  19. workFlow学习总结-----------workFlow简介
  20. Linux基础笔记18 | 磁盘分区管理

热门文章

  1. python人工智能——机器学习——特征工程
  2. 【Qt】Qt登录对话框(设计器实现)
  3. mysql 从库 read only_mysql salve从库设置read only 属性
  4. python中requests的常用方法_Python爬虫简介(2)——请求库的常用方法及使用,python,入门,二,requests,常见,和,库中,文官,网...
  5. linux 查看正在执行的进程的pid编号_不小心执行 rm f,该如何恢复?
  6. 鸿蒙开发者目前人数,苹果时隔两年公布大中华区开发者数据:440万,增长76%
  7. Linux学习笔记 文件读写小细节
  8. java8 大到小排序,屌炸天,JDK8的排序大法!!
  9. vue切换路由页面数据缓存_Vue-Router实现前端页面缓存
  10. POJ 2483 Cows(树状数组)