D1. Set To Max (Easy Version)
题意:我们给定两个长度均为n的数组a和b,我们可以进行的操作是,从a中选一段区间[l,r],将这段区间内的a[i]全部改成这段区间的最大值,问最后能否使a变成b
思路:我们想这个操作只能让小数变成大数,那么对与a[ i ]>b[ i ]的情况一定不行,其余情况我们继续分析,对于a[ i ]<b[ i ] 我们肯定要从a的两侧找到一个等于b[ i ]的a[ j ],且a[ j ]一定要为i~j的最大值,才可以让a[ i ]变为a[ j ],更重要的是,我们这样改一个区间,会不会让 i~j里面出现a[i]>b[i],
综上,我们左右两边查找距离最近且值与b[ i ]值相同的点,只要找到的元素与a[ i ]之间不存在更大的元素,且这段区间内的b[ j ] 均大于等于b[ i ] ,那么就可以完成修改,两边有一边满足即可。
#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define lowbit(x) x & (-x)
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define LF(x) fixed << setprecision(x)
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Yshanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 1e9 + 7, P = 13331;
const double eps = 1e-8;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
vector<int> b(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i];
auto check = [&](int x) -> bool
{
if (a[x] == b[x]) // 相等一定可以
return 1;
if (a[x] > b[x]) // 比b[x]还大,由于只能变大故不能实现
return 0;
int l = x, r = x;
bool f1 = 0, f2 = 0;
for (int i = x - 1; i >= 1; i--) // 找左右两边等于b[x]的a[j],如果出现大于b[x]的则不行,或者b[i]<b[x]这个个上面比b[x]还大,由于只能变大故不能实现一样
{
if (a[i] > b[x] || b[i] < b[x])
{
f1 = 1;
break;
}
if (a[i] == b[x])
{
l = i;
break;
}
}
for (int i = x + 1; i <= n; i++)
{
if (a[i] > b[x] || b[i] < b[x])
{
f2 = 1;
break;
}
if (a[i] == b[x])
{
r = i;
break;
}
}
if (r == x)
f2 = 1;
if (l == x)
f1 = 1;
if (f1 && f2) // 两边有一边就可以实现
return 0;
return 1;
};
for (int i = 1; i <= n; i++)
{
if (!check(i))
{
cout << "NO" << endl;
return;
}
}
cout << "YES" << endl;
}
signed main()
{
Yshanqian;
int T;
T = 1;
cin >> T;
for (int cases = 1; cases <= T; ++cases)
{
// cout<<"Case #"<<cases<<": ";
solve();
}
return 0;
}
D2. Set To Max (Hard Version)
思路:
按照值存下标,二分找最近的L和R
ST表预处理 a区间最大值 和 b区间最小值 即可解
或者线段树区间求区间最值也可以,就是写起来有点长
#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define lowbit(x) x & (-x)
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define LF(x) fixed << setprecision(x)
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Yshanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 1e9 + 7, P = 13331;
const double eps = 1e-8;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
vector<int> b(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i];
vector<vector<int>> f(n + 1, vector<int>(21));
vector<vector<int>> g(n + 1, vector<int>(21));
auto init = [&]() -> void
{
for (int j = 0; j <= 20; j++)
{
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
if (!j)
{
f[i][j] = a[i];
g[i][j] = b[i];
}
else
{
f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
g[i][j] = min(g[i][j - 1], g[i + (1 << j - 1)][j - 1]);
}
}
}
};
auto query_max = [&](int l, int r) -> int
{
int len = r - l + 1;
int k = log2(len);
return max(f[l][k], f[r - (1 << k) + 1][k]);
};
auto query_min = [&](int l, int r) -> int
{
int len = r - l + 1;
int k = log2(len);
return min(g[l][k], g[r - (1 << k) + 1][k]);
};
for (int i = 1; i <= n; i++)
{
if (a[i] > b[i])
{
cout << "NO" << endl;
return;
}
}
init();
vector<vector<int>> p(n + 1);
for (int i = 1; i <= n; i++)//防止L越界,存个下界
p[i].pb(0);
for (int i = 1; i <= n; i++)//按值存下标
p[a[i]].pb(i);
for (int i = 1; i <= n; i++)//防止R越界存个上界
p[i].pb(n + 1);
for (int i = 1; i <= n; i++)
{
bool ok = 0;
int x = b[i];
if (a[i] == b[i])
continue;
int R = upper_bound(p[x].begin(), p[x].end(), i) - p[x].begin();
int L = R - 1;//由于当前的i一定不等于b[i] 所以R-1一定为左边第一个等于x的a[j]
R = p[x][R];
L = p[x][L];
if (L != 0)
{
if (query_max(L, i) == x && query_min(L, i) == x)
{
ok = 1;
}
}
if (R != n + 1)
{
if (query_max(i, R) == x && query_min(i, R) == x)
{
ok = 1;
}
}
if (!ok)
{
cout << "NO" << endl;
return;
}
}
cout << "YES" << endl;
}
signed main()
{
Yshanqian;
int T;
T = 1;
cin >> T;
for (int cases = 1; cases <= T; ++cases)
{
// cout<<"Case #"<<cases<<": ";
solve();
}
return 0;
}