CF1718D Permutation for Burenka【贪心】
显然,两个数列相似当且仅当它们的笛卡尔树结构相同。
那么排列
然后我们会发现这个也是充分的,因为如果两个位置都满足限制但是不符合笛卡尔树结构,那么它们肯定在同一个由空位组成的连通块内,瞎交换一下总能达到合法。由此我们可以得到判定
对确定的
考虑对
同理,倒过来贪一遍可以得到
原问题是二分图完备匹配的形式,我们尝试使用 Hall 定理描述其有解性。对于这类点向区间连边的匹配问题,一个经典结论是存在完备匹配当且仅当完全包含于
因为这个太经典了所以这里就不证了。算了还是简单证一下好了,我们考虑右部选的点集
令
考虑
于是只需要求出
code
/*
最黯淡的一个 梦最为炽热
万千孤单焰火 让这虚构灵魂鲜活
至少在这一刻 热爱不问为何
存在为将心声响彻
*/
#include <bits/stdc++.h>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define int long long
#define mem(x, v) memset(x, v, sizeof(x))
#define mcpy(x, y, n) memcpy(x, y, sizeof(int) * (n))
#define lob lower_bound
#define upb upper_bound
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using namespace std;
inline int read() {
int x = 0, w = 1;char ch = getchar();
while (ch > '9' || ch < '0') { if (ch == '-')w = -1;ch = getchar(); }
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * w;
}
const int MN = 3e5 + 5;
const int Mod = 1e9 + 7;
const int inf = 1e9;
inline int min(int x, int y) { return x < y ? x : y; }
inline int max(int x, int y) { return x > y ? x : y; }
inline int qPow(int a, int b = Mod - 2, int ret = 1) {
while (b) {
if (b & 1) ret = ret * a % Mod;
a = a * a % Mod, b >>= 1;
}
return ret;
}
#define dbg
int N, Q, K, fl, p[MN], a[MN], d[MN];
int stk[MN], tp, ls[MN], rs[MN], f[MN];
vector <pii> vr;
inline void dfs1(int u) {
if (!u) return;
dfs1(ls[u]), dfs1(rs[u]);
if (a[u]) f[u] = a[u] + 1;
else f[u] = max(1, max(f[ls[u]], f[rs[u]]));
}
inline void dfs2(int u, int rb) {
if (!u) return;
if (!a[u]) vr.pb(mp(f[u], rb));
else fl |= f[u] > rb, rb = a[u] - 1;
dfs2(ls[u], rb), dfs2(rs[u], rb);
}
inline void work() {
N = read(), Q = read();
for (int i = 1; i <= N; i++)
p[i] = read(), ls[i] = rs[i] = 0;
tp = 0;
for (int i = 1; i <= N; i++) {
while (tp && p[stk[tp]] < p[i]) ls[i] = stk[tp--];
rs[stk[tp]] = i;
stk[++tp] = i;
}
ls[0] = rs[0] = fl = 0;
K = 0, vr.clear();
for (int i = 1; i <= N; i++)
a[i] = read(), K += !a[i];
dfs1(stk[1]);
dfs2(stk[1], inf);
set <int> s;
for (int i = 1; i < K; i++)
d[i] = read(), s.insert(d[i]);
int L = 0, R = inf;
auto cmp1 = [&](pii x, pii y) {
return x.fi > y.fi;
};
sort(vr.begin(), vr.end(), cmp1);
for (auto it : vr) {
int l = it.fi, r = it.se;
auto p = s.upb(r);
if (p == s.begin() || *--p < l) {
if (L) { fl = 1; break; }
L = l;
} else {
s.erase(p);
}
}
auto cmp2 = [&](pii x, pii y) {
return x.se < y.se;
};
sort(vr.begin(), vr.end(), cmp2);
s.clear();
for (int i = 1; i < K; i++) s.insert(d[i]);
for (auto it : vr) {
int l = it.fi, r = it.se;
auto p = s.lob(l);
if (p == s.end() || *p > r) {
if (R < inf) { fl = 1; break; }
R = r;
} else {
s.erase(p);
}
}
while (Q--) {
int x = read();
puts(!fl && L <= x && x <= R ? "YES" : "NO");
}
}
signed main(void) {
int T = read();
while (T--) work();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】