CF452F Permutation 与 P2757 [国家集训队] 等差子序列 题解
两道基本一样的题:
题目链接:
Permutation 链接:CF 或者 洛谷
等差子序列那题其实就是长度不小于 \(3\) 的等差数列是否存在,我们考虑等于 \(3\) 的是否存在就行,因为等于 \(3\) 长度的都不存在,更长的就不可能了,然后多了一个多测前提,就没啥了。两题其实基本一致。
考虑一下等差数列的三项,我们考虑中间那项设做 \(mid\),那么很显然一点,假如有公差为 \(diff\),那么应该有 \(mid-diff\) 和 \(mid+diff\) 为它的前后两项,而这个 \(diff\) 直接去确认它的存在性,过于困难,不仅要保证值的存在,值还应该处于当前 \(mid\) 所在值的两侧。而且枚举 \(diff\) 过于慢,那么其实这个时候我们可以考虑 “正难则反” 思想。既然找存在性很困难,不如考虑不存在性的条件:
注意到原序列为排列,所以里面的数不重不漏且唯一。
基于第一点,那么对于 \(mid-diff\) 或者 \(mid+diff\) 要么在 \(mid\) 之前要么在它之后,我们如果从左往右更新到了 \(mid\) 发现没有找到 \(mid-diff\) 或者 \(mid+diff\),那么它们二者不存在于 \(mid\) 前面的一定在它后面的。

以这张图为例,比如从左往依次加入值,这里我们可以考虑把所有值放在一个轴上,类似权值线段树,在这个轴处记录加入这个值,考虑比如 \(mid-diff\) 很显然它有可能在 \(mid\) 之前更新,也有可能在之后更新,总而言之,它至少应该在某一侧。假如 \(mid-diff\) 与 \(mid+diff\) 都在同一侧,显然这种情况是不可取的了。现在我们考虑让 \(diff\) 动起来,如果所有的 \(diff\) 都不满足呢?很显然有这么一张图:

在权值轴上,这些数不同的 \(diff\) 都出现了,因为我们都是从左往右更新的,所以一旦出现了说明一定是在 \(mid\) 的左侧下标范围出现的,都没出现就是都在右边下标范围,我们惊讶的发现,如果全都在同侧,那么很显然,在这个所有的 \(diff\) 出现的数是对称?
具体的,我们假如出现过的数标 \(1\),没出现的标 \(0\),那么从左往右依次加入每个数,也依次枚举每个数当 \(mid\),我们惊讶的发现当前 \(mid\) 对应的权值轴情况如果是一个对称图形:

例如这样,就表示:所有的对应 \(diff\) 对都是处于同一侧的,不存在异侧,即不存在解。。那问题就转变为了找不存在性即为判断权值轴是否是回文的,对称的,那自然而然的相当最简单的方法:维护权值轴信息自然而然用权值线段树,判断回文吗?考虑到线段树还可以同时维护信息,所以我们考虑使用哈希作为判断条件,为每个树节点维护两种哈希,一种是从左往右,一种从右往左,具体的:
例如:\(1011\) 这个数从左往右就是 \(1011\) 的哈希,从右往左就是 \(1101\) 的哈希。如果两种哈希相同,自然就是回文对称了。
线段树维护哈希挺简单的,首先确定模数,然后确定下底数,这里就写单哈希了。具体的,再预处理个底数的幂次方数组,当合并线段树节点信息 \(pushUp\) 的时候,注意是哪种哈希,从左往右的自然是,左边子树往右移动了 \(rightLen\) 位,举个例子:

显然从左往右合并的答案为:\(1011\),从右往左就是 \(1110\) 了,谁拼谁罢了。乘个偏移信息以后加上另一边然后记得取模就行了。如果不满足回文,显然就是有解了,至此问题全部解决。
CF题目参考代码
#include <bits/stdc++.h>
// #pragma GCC optimize("Ofast,unroll-loops")
// #pragma GCC optimize(2)
// #define isPbdsFile
#ifdef isPbdsFile
#include <bits/extc++.h>
#else
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/list_update_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/exception.hpp>
#include <ext/rope>
#endif
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tii;
typedef tuple<ll, ll, ll> tll;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef __int128 i128;
#define hash1 unordered_map
#define hash2 gp_hash_table
#define hash3 cc_hash_table
#define stdHeap std::priority_queue
#define pbdsHeap __gnu_pbds::priority_queue
#define sortArr(a, n) sort(a+1,a+n+1)
#define all(v) v.begin(),v.end()
#define yes cout<<"YES"
#define no cout<<"NO"
#define Spider ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define MyFile freopen("..\\input.txt", "r", stdin),freopen("..\\output.txt", "w", stdout);
#define forn(i, a, b) for(int i = a; i <= b; i++)
#define forv(i, a, b) for(int i=a;i>=b;i--)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define endl '\n'
//用于Miller-Rabin
[[maybe_unused]] static int Prime_Number[13] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
template <typename T>
int disc(T* a, int n)
{
return unique(a + 1, a + n + 1) - (a + 1);
}
template <typename T>
T lowBit(T x)
{
return x & -x;
}
template <typename T>
T Rand(T l, T r)
{
static mt19937 Rand(time(nullptr));
uniform_int_distribution<T> dis(l, r);
return dis(Rand);
}
template <typename T1, typename T2>
T1 modt(T1 a, T2 b)
{
return (a % b + b) % b;
}
template <typename T1, typename T2, typename T3>
T1 qPow(T1 a, T2 b, T3 c)
{
a %= c;
T1 ans = 1;
for (; b; b >>= 1, (a *= a) %= c)if (b & 1)(ans *= a) %= c;
return modt(ans, c);
}
template <typename T>
void read(T& x)
{
x = 0;
T sign = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')sign = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
x *= sign;
}
template <typename T, typename... U>
void read(T& x, U&... y)
{
read(x);
read(y...);
}
template <typename T>
void write(T x)
{
if (typeid(x) == typeid(char))return;
if (x < 0)x = -x, putchar('-');
if (x > 9)write(x / 10);
putchar(x % 10 ^ 48);
}
template <typename C, typename T, typename... U>
void write(C c, T x, U... y)
{
write(x), putchar(c);
write(c, y...);
}
template <typename T11, typename T22, typename T33>
struct T3
{
T11 one;
T22 tow;
T33 three;
bool operator<(const T3 other) const
{
if (one == other.one)
{
if (tow == other.tow)return three < other.three;
return tow < other.tow;
}
return one < other.one;
}
T3() { one = tow = three = 0; }
T3(T11 one, T22 tow, T33 three) : one(one), tow(tow), three(three)
{
}
};
template <typename T1, typename T2>
void uMax(T1& x, T2 y)
{
if (x < y)x = y;
}
template <typename T1, typename T2>
void uMin(T1& x, T2 y)
{
if (x > y)x = y;
}
constexpr int N = 3e5 + 10;
constexpr int MX = 3e5;
constexpr int MOD = 1e9 + 7;
constexpr int BASE = 33;
ll powBase[N];
struct Node
{
ll val, revVal; //正反哈希
int len; //区间长度
} node[N << 2];
int n;
#define val(x) node[x].val
#define revVal(x) node[x].revVal
#define len(x) node[x].len
inline void push_up(const int curr)
{
val(curr) = (val(ls(curr)) * powBase[len(rs(curr))] + val(rs(curr))) % MOD;
revVal(curr) = (revVal(ls(curr)) + revVal(rs(curr)) * powBase[len(ls(curr))]) % MOD;
}
inline void add(const int curr, const int pos, const int l = 1, const int r = n)
{
const int mid = l + r >> 1;
if (l == r)
{
val(curr) = revVal(curr) = 1;
return;
}
if (pos <= mid)add(ls(curr), pos, l, mid);
else add(rs(curr), pos, mid + 1, r);
push_up(curr);
}
inline pll query(const int curr, const int l, const int r, const int s = 1, const int e = n)
{
if (l <= s and e <= r)return pll(val(curr),revVal(curr));
const int mid = s + e >> 1;
if (r <= mid)return query(ls(curr), l, r, s, mid);
if (l > mid)return query(rs(curr), l, r, mid + 1, e);
auto [leftVal,leftRevVal] = query(ls(curr), l, mid, s, mid);
auto [rightVal,rightRevVal] = query(rs(curr), mid + 1, r, mid + 1, e);
auto ansVal = (leftVal * powBase[r - mid] + rightVal) % MOD;
auto ansRevVal = (leftRevVal + rightRevVal * powBase[mid - l + 1]) % MOD;
return pll(ansVal, ansRevVal);
}
inline void build(const int curr = 1, const int l = 1, const int r = n)
{
len(curr) = r - l + 1;
val(curr) = revVal(curr) = 0;
const int mid = l + r >> 1;
if (l == r)return;
build(ls(curr), l, mid);
build(rs(curr), mid + 1, r);
}
int x;
inline void solve()
{
cin >> n;
build();
bool check = false;
forn(i, 1, n)
{
cin >> x;
auto minLen = min(x - 1, n - x);
auto [val1,val2] = query(1, x - minLen, x + minLen);
if (val1 != val2)check = true;
add(1, x);
}
cout << (check ? "YES" : "NO") << endl;
}
signed int main()
{
// MyFile
Spider
//------------------------------------------------------
// clock_t start = clock();
powBase[0] = 1;
forn(i, 1, MX)powBase[i] = powBase[i - 1] * BASE % MOD;
int test = 1;
// read(test);
// cin >> test;
forn(i, 1, test)solve();
// while (cin >> n, n)solve();
// while (cin >> test)solve();
// clock_t end = clock();
// cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
}
洛谷题目参考代码
#include <bits/stdc++.h>
// #pragma GCC optimize("Ofast,unroll-loops")
// #pragma GCC optimize(2)
// #define isPbdsFile
#ifdef isPbdsFile
#include <bits/extc++.h>
#else
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/list_update_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/exception.hpp>
#include <ext/rope>
#endif
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tii;
typedef tuple<ll, ll, ll> tll;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef __int128 i128;
#define hash1 unordered_map
#define hash2 gp_hash_table
#define hash3 cc_hash_table
#define stdHeap std::priority_queue
#define pbdsHeap __gnu_pbds::priority_queue
#define sortArr(a, n) sort(a+1,a+n+1)
#define all(v) v.begin(),v.end()
#define yes cout<<"YES"
#define no cout<<"NO"
#define Spider ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define MyFile freopen("..\\input.txt", "r", stdin),freopen("..\\output.txt", "w", stdout);
#define forn(i, a, b) for(int i = a; i <= b; i++)
#define forv(i, a, b) for(int i=a;i>=b;i--)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define endl '\n'
//用于Miller-Rabin
[[maybe_unused]] static int Prime_Number[13] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
template <typename T>
int disc(T* a, int n)
{
return unique(a + 1, a + n + 1) - (a + 1);
}
template <typename T>
T lowBit(T x)
{
return x & -x;
}
template <typename T>
T Rand(T l, T r)
{
static mt19937 Rand(time(nullptr));
uniform_int_distribution<T> dis(l, r);
return dis(Rand);
}
template <typename T1, typename T2>
T1 modt(T1 a, T2 b)
{
return (a % b + b) % b;
}
template <typename T1, typename T2, typename T3>
T1 qPow(T1 a, T2 b, T3 c)
{
a %= c;
T1 ans = 1;
for (; b; b >>= 1, (a *= a) %= c)if (b & 1)(ans *= a) %= c;
return modt(ans, c);
}
template <typename T>
void read(T& x)
{
x = 0;
T sign = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')sign = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
x *= sign;
}
template <typename T, typename... U>
void read(T& x, U&... y)
{
read(x);
read(y...);
}
template <typename T>
void write(T x)
{
if (typeid(x) == typeid(char))return;
if (x < 0)x = -x, putchar('-');
if (x > 9)write(x / 10);
putchar(x % 10 ^ 48);
}
template <typename C, typename T, typename... U>
void write(C c, T x, U... y)
{
write(x), putchar(c);
write(c, y...);
}
template <typename T11, typename T22, typename T33>
struct T3
{
T11 one;
T22 tow;
T33 three;
bool operator<(const T3 other) const
{
if (one == other.one)
{
if (tow == other.tow)return three < other.three;
return tow < other.tow;
}
return one < other.one;
}
T3() { one = tow = three = 0; }
T3(T11 one, T22 tow, T33 three) : one(one), tow(tow), three(three)
{
}
};
template <typename T1, typename T2>
void uMax(T1& x, T2 y)
{
if (x < y)x = y;
}
template <typename T1, typename T2>
void uMin(T1& x, T2 y)
{
if (x > y)x = y;
}
constexpr int N = 5e5 + 10;
constexpr int MX = 5e5;
constexpr int MOD = 1e9 + 7;
constexpr int BASE = 33;
ll powBase[N];
struct Node
{
ll val, revVal; //正反哈希
int len; //区间长度
} node[N << 2];
int n;
#define val(x) node[x].val
#define revVal(x) node[x].revVal
#define len(x) node[x].len
inline void push_up(const int curr)
{
val(curr) = (val(ls(curr)) * powBase[len(rs(curr))] + val(rs(curr))) % MOD;
revVal(curr) = (revVal(ls(curr)) + revVal(rs(curr)) * powBase[len(ls(curr))]) % MOD;
}
inline void add(const int curr, const int pos, const int l = 1, const int r = n)
{
const int mid = l + r >> 1;
if (l == r)
{
val(curr) = revVal(curr) = 1;
return;
}
if (pos <= mid)add(ls(curr), pos, l, mid);
else add(rs(curr), pos, mid + 1, r);
push_up(curr);
}
inline pll query(const int curr, const int l, const int r, const int s = 1, const int e = n)
{
if (l <= s and e <= r)return pll(val(curr),revVal(curr));
const int mid = s + e >> 1;
if (r <= mid)return query(ls(curr), l, r, s, mid);
if (l > mid)return query(rs(curr), l, r, mid + 1, e);
auto [leftVal,leftRevVal] = query(ls(curr), l, mid, s, mid);
auto [rightVal,rightRevVal] = query(rs(curr), mid + 1, r, mid + 1, e);
auto ansVal = (leftVal * powBase[r - mid] + rightVal) % MOD;
auto ansRevVal = (leftRevVal + rightRevVal * powBase[mid - l + 1]) % MOD;
return pll(ansVal, ansRevVal);
}
inline void build(const int curr = 1, const int l = 1, const int r = n)
{
len(curr) = r - l + 1;
val(curr) = revVal(curr) = 0;
const int mid = l + r >> 1;
if (l == r)return;
build(ls(curr), l, mid);
build(rs(curr), mid + 1, r);
}
int x;
inline void solve()
{
cin >> n;
build();
bool check = false;
forn(i, 1, n)
{
cin >> x;
auto minLen = min(x - 1, n - x);
auto [val1,val2] = query(1, x - minLen, x + minLen);
if (val1 != val2)check = true;
add(1, x);
}
cout << (check ? "Y" : "N") << endl;
}
signed int main()
{
// MyFile
Spider
//------------------------------------------------------
// clock_t start = clock();
powBase[0] = 1;
forn(i, 1, MX)powBase[i] = powBase[i - 1] * BASE % MOD;
int test = 1;
// read(test);
cin >> test;
forn(i, 1, test)solve();
// while (cin >> n, n)solve();
// while (cin >> test)solve();
// clock_t end = clock();
// cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
}
\]
CF452F Permutation 与 P2757 [国家集训队] 等差子序列 题解的更多相关文章
- luogu P2757 [国家集训队]等差子序列
题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...
- P2757 [国家集训队]等差子序列
P2757 [国家集训队]等差子序列 题目传送门 推荐一篇好题解 此题要求我们在一个序列中找出一个等差子序列. 显然,我们只需要考虑子序列长度len=3的情况,因为在长度为4的子序列中必定有一个长度为 ...
- 洛谷 P2757 [国家集训队]等差子序列 解题报告
P2757 [国家集训队]等差子序列 题目描述 给一个\(1\)到\(N\)的排列\(\{A_i\}\),询问是否存在 \[1 \le p_1<p_2<p_3<p_4<p_5& ...
- 洛谷P2172 [国家集训队]部落战争 题解
题目链接:https://www.luogu.org/problemnew/show/P2172 分析: 不要被[国家集训队]的标签吓到,其实这题不是很难. 本题可以对比P4304 [TJOI2013 ...
- [BZOJ2124]等差子序列/[CF452F]Permutation
[BZOJ2124]等差子序列/[CF452F]Permutation 题目大意: 一个\(1\sim n\)的排列\(A_{1\sim n}\),询问是否存在\(i,j(i<j)\),使得\( ...
- 1893. [国家集训队2011]等差子序列(bitset)
★★ 输入文件:nt2011_sequence.in 输出文件:nt2011_sequence.out 简单对比时间限制:0.3 s 内存限制:512 MB [试题来源] 2011中国 ...
- CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash
传送门--Luogu 传送门--Codeforces 如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列.可以枚举等差子 ...
- [国家集训队2012]middle
http://cogs.pro:8080/cogs/problem/problem.php?pid=1763 二分答案x 把区间内>=x的数设为1,<x的数设为-1 左端点在[a,b]之间 ...
- Good Triple CodeForces - 1169D (等差子序列)
大意: 给定01字符串, 求有多少个区间$[l,r]$, 使得存在正整数$x,k$满足$1\le x,k\le n,l\le x<x+2k\le r,s_x=s_{x+k}=s_{x+2k}$. ...
- BZOJ 2039: [2009国家集训队]employ人员雇佣
2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1369 Solved: 667[Submit ...
随机推荐
- 传统单节点网站的 Serverless 上云
什么是函数?刚刚考完数学没多久的我,脑里立马想到的是自变量.因变量.函数值,也就是y=f(x).当然,在计算机里,函数function往往指的是一段被定义好的代码程序,我们可以通过传参调用这个定义好的 ...
- vue 状态管理 二、状态管理的基本使用
系列导航 vue 状态管理 一.状态管理概念和基本结构 vue 状态管理 二.状态管理的基本使用 vue 状态管理 三.Mutations和Getters用法 vue 状态管理 四.Action用法 ...
- 四、swift大对象--静态态大对象
系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...
- 报错:for..in loops iterate over the entire prototype chain, which is virtually never what you want.
for..in loops iterate over the entire prototype chain, which is virtually never what you want. 意思是使用 ...
- linux chown 与 chmod 命令的使用
本文为博主原创,未经允许不得转载: 最近在做 linux 系统安全管理检查操作,频繁的用到了 chown 与 chmod 两个命令,觉得有必要对着两个命令总结一下. 一. chown 命令: 1. 设 ...
- Java标签在循环中的使用
定义 标签,类似--label1: 放在循环外部,用于内部多重循环语句的跳出 例子 public static void main(String[] args) { Scanner sc = new ...
- Oracle数据库如何解决创建用户名开头必须要C##问题?
1.问题 我们在创建用户,概要文件等时,由于使用的是容器数据库,其文件名必须以C##开头. 我们在学习过程中暂时不需要对齐进行区分,所以如何修改这个设定呢? 2.解决 参考链接如何解决创建用户名开头必 ...
- 【SHELL】命令补全
# 指定文件 dodo_path=/home/skull/work/scripts/dodo echo "hello skull" ## COMP_WORDS 是一个 bash 内 ...
- [转帖]Rust在windows下安装以后cargo build Error: linker `link.exe` not found
D:\rust\runoob-greeting\greeting>cargo build error: linker `link.exe` not found | = note: 系统找不到指定 ...
- [转帖]SSL Certificate Exporter
https://github.com/ribbybibby/ssl_exporter Exports metrics for certificates collected from various s ...