Goodbye Yiwei
A
贪心的取,后缀 min 比栈顶和栈底小就一直取到后缀 \min,否则取栈顶和栈底中最小的。
#include <bits/stdc++.h>
#define IL __inline__ __attribute__((always_inline))
#define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
#define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
#define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
#define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
typedef long long LL;
template <class T>
IL bool chkmax(T &a, const T &b) {
return a < b ? ((a = b), 1) : 0;
}
template <class T>
IL bool chkmin(T &a, const T &b) {
return a > b ? ((a = b), 1) : 0;
}
template <class T>
IL T mymax(const T &a, const T &b) {
return a > b ? a : b;
}
template <class T>
IL T mymin(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
IL T myabs(const T &a) {
return a > 0 ? a : -a;
}
const int INF = 0X3F3F3F3F;
const double EPS = 1E-8, PI = acos(-1.0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define OK DEBUG("Passing [%s] in LINE %d...\n", __FUNCTION__, __LINE__)
#define SZ(x) ((int)(x).size())
const int MAXN = 100000 + 5;
std::deque<int> dq;
int a[MAXN], suf[MAXN];
int main() {
int T;
scanf("%d", &T);
while (T --) {
dq.clear();
int n;
scanf("%d", &n);
For(i, 1, n) {
scanf("%d", &a[i]);
}
suf[n + 1] = INF;
Rep(i, n, 1) {
suf[i] = mymin(suf[i + 1], a[i]);
}
int cur = 1, cnt = 0;
while (cnt < n) {
while (dq.empty() || mymin(dq.front(), dq.back()) > suf[cur]) {
dq.push_back(a[cur ++]);
}
while (!dq.empty() && mymin(dq.front(), dq.back()) < suf[cur]) {
if (dq.front() < dq.back()) {
printf("%d ", dq.front());
dq.pop_front();
} else {
printf("%d ", dq.back());
dq.pop_back();
}
++ cnt;
}
}
puts("");
}
return 0;
}
B
一个点是安全的当且仅当:
1.它的度数为 1;
2.它和一个度数为 1 的点相连;
3.存在一个点,忽略它和这个点的连边后这两个点相邻的点相同。
前两个条件很好判断,第三个条件如果两个点不相邻排个序就行了,相邻的话直接枚举每条边然后暴力判断即可。
这个暴力复杂度是对的,因为它等价于这个式子:
每个点至多贡献 O(\sqrt{m}) 次,而所有点的度数和为 O(m),所以复杂度是 O(m\sqrt{m})。
#include <bits/stdc++.h>
#define IL __inline__ __attribute__((always_inline))
#define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
#define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
#define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
#define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
typedef long long LL;
template <class T>
IL bool chkmax(T &a, const T &b) {
return a < b ? ((a = b), 1) : 0;
}
template <class T>
IL bool chkmin(T &a, const T &b) {
return a > b ? ((a = b), 1) : 0;
}
template <class T>
IL T mymax(const T &a, const T &b) {
return a > b ? a : b;
}
template <class T>
IL T mymin(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
IL T myabs(const T &a) {
return a > 0 ? a : -a;
}
const int INF = 0X3F3F3F3F;
const double EPS = 1E-8, PI = acos(-1.0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define OK DEBUG("Passing [%s] in LINE %d...\n", __FUNCTION__, __LINE__)
#define SZ(x) ((int)(x).size())
struct Input {
char buf[1 << 25], *s;
Input() {
#ifndef ONLINE_JUDGE
freopen("police.in", "r", stdin);
#endif
fread(s = buf, 1, 1 << 25, stdin);
}
friend Input &operator>>(Input &io, int &x) {
x = 0;
while (!isdigit(*io.s)) {
++ io.s;
}
while (isdigit(*io.s)) {
x = x * 10 + *io.s ++ - '0';
}
return io;
}
} cin;
const int MAXN = 100000 + 5, MAXM = 200000 + 5;
struct Edge {
int u, v;
} edge[MAXM];
std::vector<int> adj[MAXN];
std::pair<std::vector<int>, int> tp[MAXN];
int deg[MAXN];
bool ok[MAXN];
int main() {
int T;
cin >> T;
while (T --) {
int n, m;
cin >> n >> m;
memset(deg, 0, sizeof deg);
memset(ok, 0, sizeof ok);
For(i, 1, n) {
adj[i].clear();
}
For(i, 1, m) {
cin >> edge[i].u >> edge[i].v;
++ deg[edge[i].u], ++ deg[edge[i].v];
adj[edge[i].u].push_back(edge[i].v);
adj[edge[i].v].push_back(edge[i].u);
}
For(i, 1, n) {
std::sort(adj[i].begin(), adj[i].end());
tp[i] = {adj[i], i};
}
std::sort(tp + 1, tp + n + 1);
FOR(i, 1, n) {
if (tp[i].first == tp[i + 1].first) {
ok[tp[i].second] = ok[tp[i + 1].second] = 1;
}
}
For(i, 1, m) {
if (deg[edge[i].u] == 1 || deg[edge[i].v] == 1) {
ok[edge[i].u] = ok[edge[i].v] = 1;
}
}
For(i, 1, m) {
if ((!ok[edge[i].u] || !ok[edge[i].v]) && deg[edge[i].u] == deg[edge[i].v]) {
int u = edge[i].u, v = edge[i].v;
bool yes = 1;
for (int x = 0, y = 0; x < SZ(adj[u]) && y < SZ(adj[v]); ++ x, ++ y) {
if (adj[u][x] == v) {
++ x;
}
if (adj[v][y] == u) {
++ y;
}
if (x >= SZ(adj[u]) || y >= SZ(adj[v])) {
break;
}
if (adj[u][x] != adj[v][y]) {
yes = 0;
break;
}
}
if (yes) {
ok[u] = ok[v] = 1;
}
}
}
int cnt = 0;
For(i, 1, n) {
cnt += ok[i];
}
printf("%d\n", cnt);
For(i, 1, n) {
if (ok[i]) {
printf("%d ", i);
}
}
puts("");
}
return 0;
}
C
考虑 Boruvka 算法,每轮给每个连通块赋一个颜色,然后逐位确定最大连边的权值,可以发现你实际上要求的是某个集合的超集的最大值和次大值(为了判断是否只有一种颜色),高维前缀和即可。
#include <bits/stdc++.h>
#define IL __inline__ __attribute__((always_inline))
#define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
#define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
#define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
#define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
typedef long long LL;
template <class T>
IL bool chkmax(T &a, const T &b) {
return a < b ? ((a = b), 1) : 0;
}
template <class T>
IL bool chkmin(T &a, const T &b) {
return a > b ? ((a = b), 1) : 0;
}
template <class T>
IL T mymax(const T &a, const T &b) {
return a > b ? a : b;
}
template <class T>
IL T mymin(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
IL T myabs(const T &a) {
return a > 0 ? a : -a;
}
const int INF = 0X3F3F3F3F;
const double EPS = 1E-8, PI = acos(-1.0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define OK DEBUG("Passing [%s] in LINE %d...\n", __FUNCTION__, __LINE__)
#define SZ(x) ((int)(x).size())
const int MAXN = 100000 + 5, MASK = 1 << 18;
struct DisjointSet {
int fa[MAXN];
void init(int n) {
For(i, 1, n) {
fa[i] = i;
}
}
int find(int u) {
return fa[u] == u ? u : fa[u] = find(fa[u]);
}
bool same(int u, int v) {
return find(u) == find(v);
}
void merge(int u, int v) {
if (!same(u, v)) {
fa[fa[v]] = fa[u];
}
}
} dsu;
int a[MAXN], col[MAXN], tp[MAXN], to[MAXN], val[MAXN], col_sec[MASK], col_max[MASK], num_sec[MASK], num_max[MASK];
int main() {
#ifndef ONLINE_JUDGE
freopen("andmst.in", "r", stdin);
#endif
int n, m;
scanf("%d%d", &n, &m);
For(i, 1, n) {
scanf("%d", &a[i]);
}
int cnt = 0, cur = n;
For(i, 1, n) {
col[i] = i;
}
LL ans = 0;
while (cnt < n - 1) {
dsu.init(cur);
memset(col_sec, 0, sizeof col_sec);
memset(col_max, 0, sizeof col_max);
memset(num_sec, 0, sizeof num_sec);
memset(num_max, 0, sizeof num_max);
For(i, 1, n) {
if (col_max[a[i]] < col[i]) {
col_sec[a[i]] = col_max[a[i]];
col_max[a[i]] = col[i];
num_sec[a[i]] = num_max[a[i]];
num_max[a[i]] = i;
} else if (col_max[a[i]] != col[i] && col_sec[a[i]] < col[i]) {
col_sec[a[i]] = col[i];
num_sec[a[i]] = i;
}
}
FOR(i, 0, m) {
REP(S, 1 << m, 0) {
if ((~S >> i) & 1) {
if (col_max[S] < col_max[S | (1 << i)]) {
col_sec[S] = col_max[S];
col_max[S] = col_max[S | (1 << i)];
num_sec[S] = num_max[S];
num_max[S] = num_max[S | (1 << i)];
if (col_sec[S] < col_sec[S | (1 << i)]) {
col_sec[S] = col_sec[S | (1 << i)];
num_sec[S] = num_sec[S | (1 << i)];
}
} else if (col_max[S] != col_max[S | (1 << i)] && col_sec[S] < col_max[S | (1 << i)]) {
col_sec[S] = col_max[S | (1 << i)];
num_sec[S] = num_max[S | (1 << i)];
} else if (col_max[S] == col_max[S | (1 << i)] && col_sec[S] < col_sec[S | (1 << i)]) {
col_sec[S] = col_sec[S | (1 << i)];
num_sec[S] = num_sec[S | (1 << i)];
}
}
}
}
For(i, 1, cur) {
to[i] = 0, val[i] = -1;
}
For(i, 1, n) {
int s = 0;
REP(j, m, 0) {
if ((a[i] >> j) & 1) {
int t = s << 1 | 1, p = t << j;
if (col_max[p] && (col_max[p] != col[i] || (col_sec[p] && col_sec[p] != col[i]))) {
s = t;
} else {
s = t - 1;
}
} else {
s <<= 1;
}
}
int v = col_max[s] == col[i] ? num_sec[s] : num_max[s], w = a[i] & a[v];
if (chkmax(val[col[i]], w)) {
to[col[i]] = col[v];
}
}
For(i, 1, cur) {
if (!dsu.same(i, to[i])) {
dsu.merge(i, to[i]);
++ cnt;
ans += val[i];
}
}
int fn = 0;
For(i, 1, cur) {
if (dsu.find(i) == i) {
tp[i] = ++ fn;
}
}
For(i, 1, cur) {
tp[i] = tp[dsu.find(i)];
}
For(i, 1, n) {
col[i] = tp[col[i]];
}
cur = fn;
}
printf("%lld\n", ans);
return 0;
}
D
先二分答案,然后考虑倒着做,把合并变成划分,然后就变成了你初始有一个雷,每次你可以把一个威力为 k 的雷变成 m 个威力为 \{k - b_1, k - b_2, \cdots, k - b_m\} 的雷,最后要让排序后每个雷的威力都大于等于对应位置的 a_i。
我们称雷的集合 S 可以匹配集合 T,当且仅当 S 可以通过一系列拆分操作使得 |S| = |T|,且排序后 S 中对应位置的雷的威力都大于 T 中的。
每次考虑 S 中最大的雷能否拆出能匹配 T 中最大的雷的雷,否则就把 T 中最大的雷匹配掉,用 multiset 维护即可。
#include <bits/stdc++.h>
#define IL __inline__ __attribute__((always_inline))
#define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
#define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
#define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
#define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
typedef long long LL;
template <class T>
IL bool chkmax(T &a, const T &b) {
return a < b ? ((a = b), 1) : 0;
}
template <class T>
IL bool chkmin(T &a, const T &b) {
return a > b ? ((a = b), 1) : 0;
}
template <class T>
IL T mymax(const T &a, const T &b) {
return a > b ? a : b;
}
template <class T>
IL T mymin(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
IL T myabs(const T &a) {
return a > 0 ? a : -a;
}
const int INF = 0X3F3F3F3F;
const double EPS = 1E-8, PI = acos(-1.0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define OK DEBUG("Passing [%s] in LINE %d...\n", __FUNCTION__, __LINE__)
#define SZ(x) ((int)(x).size())
const int MAXN = 50000 + 5;
int a[MAXN], b[MAXN];
IL bool check(int n, int m, LL k) {
std::multiset<LL> s({k}), t(a + 1, a + n + 1);
while (SZ(s) < SZ(t)) {
if (s.empty()) {
return 0;
}
LL x = *s.rbegin(), y = *t.rbegin();
if (x - b[1] >= y) {
For(i, 1, m) {
s.insert(x - b[i]);
}
s.erase(s.find(x));
} else {
auto it = s.lower_bound(y);
if (it == s.end()) {
return 0;
}
s.erase(it), t.erase(t.find(y));
}
}
for (auto x = s.begin(), y = t.begin(); x != s.end() && y != t.end(); ++ x, ++ y) {
if (*x < *y) {
return 0;
}
}
return 1;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
For(i, 1, n) {
scanf("%d", &a[i]);
}
For(i, 1, m) {
scanf("%d", &b[i]);
}
std::sort(a + 1, a + n + 1);
std::sort(b + 1, b + m + 1);
LL l = a[n], r = a[n] + (LL)(n - 1) / (m - 1) * b[m], ans = 0;
while (l <= r) {
LL mid = (l + r) >> 1;
if (check(n, m, mid)) {
ans = mid, r = mid - 1;
} else {
l = mid + 1;
}
}
printf("%lld\n", ans);
return 0;
}
E
发现如果值域是 [0,1024] 的话可以用长为 10240 的串传送,于是考虑一个 hash 函数把这 1024 个坐标映射到这个范围上去。
问题在于随机这个函数的话需要的次数太多了,考虑转换一下方法,每次把这些坐标分成两半,这样随机次数就可以接受了。
但这样需要传送的次数太多了,于是可以考虑小范围用开始的方法暴力随。
有一个问题是如果你用定长编码传送次数,那么这个定长会比较大,所以可以使用不定长编码,具体实现可以参见代码。
#include <bits/stdc++.h>
#define IL __inline__ __attribute__((always_inline))
#define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
#define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
#define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
#define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
typedef long long LL;
template <class T>
IL bool chkmax(T &a, const T &b) {
return a < b ? ((a = b), 1) : 0;
}
template <class T>
IL bool chkmin(T &a, const T &b) {
return a > b ? ((a = b), 1) : 0;
}
template <class T>
IL T mymax(const T &a, const T &b) {
return a > b ? a : b;
}
template <class T>
IL T mymin(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
IL T myabs(const T &a) {
return a > 0 ? a : -a;
}
const int INF = 0X3F3F3F3F;
const double EPS = 1E-8, PI = acos(-1.0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define OK DEBUG("Passing [%s] in LINE %d...\n", __FUNCTION__, __LINE__)
#define SZ(x) ((int)(x).size())
const int MAXN = 1024, MAXM = 20000 + 5;
IL unsigned xorShift() {
static unsigned x = 20030102;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return x;
}
struct Hash {
static const int MOD = 998244353;
int a, b;
Hash() : a(114514), b(1919810) {}
void next() {
a = xorShift() % MOD, b = xorShift() % MOD;
}
int get(unsigned x) {
return ((LL)a * x + b) % MOD;
}
} h;
namespace Encode {
unsigned key[MAXN];
int val[MAXN], to[MAXN], cur;
bool ret[MAXM];
IL void print(int x, int digit, bool mode) {
if (mode) {
int real = x ? std::__lg(x) + 1 : 0;
For(i, 1, real - digit) {
ret[cur ++] = 1;
}
ret[cur ++] = 0;
}
for (; x; x >>= 1, -- digit) {
ret[cur ++] = x & 1;
}
for (; digit > 0; -- digit) {
ret[cur ++] = 0;
}
}
void solve(const std::vector<int> &v, int high) {
static int tp[MAXN];
int times = 0;
if (SZ(v) <= 8) {
while (1) {
FOR(i, 0, 8) {
tp[i] = -1;
}
FOR(i, 0, 8) {
tp[h.get(key[v[i]]) % 8] = v[i];
}
bool ok = 1;
FOR(i, 0, 8) {
if (!~tp[i]) {
ok = 0;
break;
}
}
if (ok) {
break;
}
++ times;
h.next();
}
FOR(i, 0, 8) {
to[high << 3 | i] = tp[i];
}
print(times, 9, 1);
return;
}
int n = SZ(v);
while (1) {
FOR(i, 0, n) {
tp[i] = h.get(key[v[i]]) % 2;
}
int cnt = 0;
FOR(i, 0, n) {
cnt += tp[i];
}
if (cnt == n / 2) {
break;
}
++ times;
h.next();
}
print(times, 4, 1);
std::vector<int> x, y;
FOR(i, 0, n) {
if (tp[i]) {
y.push_back(v[i]);
} else {
x.push_back(v[i]);
}
}
solve(x, high << 1), solve(y, high << 1 | 1);
}
IL void main() {
FOR(i, 0, MAXN) {
scanf("%u%d", &key[i], &val[i]);
}
std::vector<int> v(MAXN);
FOR(i, 0, MAXN) {
v[i] = i;
}
solve(v, 0);
FOR(i, 0, MAXN) {
print(val[to[i]], 10, 0);
}
FOR(i, 0, cur) {
putchar('0' + ret[i]);
}
puts("");
}
}
namespace Decode {
unsigned val[MAXN];
int to[MAXN], ans[MAXN], cur;
int len;
char str[MAXM];
IL int read(int digit, bool mode) {
int more = 0;
if (mode) {
while (str[cur ++] == '1') {
++ more;
}
}
int ans = 0;
FOR(i, 0, digit + more) {
ans += (str[cur ++] - '0') << i;
}
return ans;
}
void solve(const std::vector<int> &v, int cur, int high) {
if (cur <= 8) {
int times = read(9, 1);
For(i, 1, times) {
h.next();
}
for (auto &x : v) {
to[high << 3 | (h.get(val[x]) % 8)] = x;
}
return;
}
int times = read(4, 1);
For(i, 1, times) {
h.next();
}
std::vector<int> x, y;
for (auto &a : v) {
if (h.get(val[a]) % 2) {
y.push_back(a);
} else {
x.push_back(a);
}
}
solve(x, cur >> 1, high << 1), solve(y, cur >> 1, high << 1 | 1);
}
IL void main() {
memset(to, -1, sizeof to);
scanf("%s", str);
len = strlen(str);
int q;
scanf("%d", &q);
std::vector<int> v(q);
FOR(i, 0, q) {
scanf("%u", &val[i]);
v[i] = i;
}
solve(v, MAXN, 0);
FOR(i, 0, MAXN) {
int x = read(10, 0);
if (to[i] != -1) {
ans[to[i]] = x;
}
}
FOR(i, 0, q) {
printf("%d\n", ans[i]);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("decode.in", "r", stdin);
freopen("decode.out", "w", stdout);
#endif
char str[10];
scanf("%s", str);
if (str[0] == 'e') {
Encode::main();
} else {
Decode::main();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)