T2 T4不太可做,所以没改
Mortis 20pts
原题:Luogu [ABC302G] Sort from 1 to 4
赛时用 $ set $ 乱搞拿了20pts,事实证明确实是乱搞;
考虑交换只有三种情况:
-
a在b上,b在a上,需要一次;
-
a在b上,b在c上,c在a上,需要两次;
-
a在b上,b在c上,c在d上,d在a上,需要三次;
这里的在什么什么上是指原数组排序后的位置;
开个二维数组统计一下即可;
点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
int a[500005];
int b[500005];
int cnt[15][15];
int ans;
int tot;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++) {
if (a[i] != b[i]) {
cnt[b[i]][a[i]]++;
tot++;
}
}
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
if (i == j) continue;
while(cnt[i][j] && cnt[j][i]) {
ans++;
cnt[i][j]--;
cnt[j][i]--;
tot -= 2;
}
}
}
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
for (int k = 1; k <= 4; k++) {
if (i == j || i == k || j == k) continue;
while(cnt[i][j] && cnt[j][k] && cnt[k][i]) {
ans += 2;
cnt[i][j]--;
cnt[j][k]--;
cnt[k][i]--;
tot -= 3;
}
}
}
}
cout << ans + tot / 4 * 3;
return 0;
}
嘉然今天吃什么 10pts
原题:Luogu P8511 [Ynoi Easy Round 2021] TEST_68
$ \Theta(n^3) $ 暴力很好写;
考虑找出一个全局最大异或点对 $ p, q $(用 $ 01 \ trie $ 处理),可以发现除了它们到根路径上的所有点以外其它点的答案都是这个最大值;
所以分别处理;
第二次处理时,需要边插入边查询,同时需要特判 $ p, q $ 的 $ lca $(分两次处理);
也是复习了一下 $ 01 \ trie $;
完事;
点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n;
struct sss{
int t, ne;
}e[2000005];
int h[2000005], cnt;
void add(int u, int v) {
e[++cnt].t = v;
e[cnt].ne = h[u];
h[u] = cnt;
}
int fa[500005], dep[500005];
long long a[500005], ans[500005];
int tot;
long long ma;
namespace trie{
int son[30000005][2];
int id[30000005];
void ins(int x) {
int now = 1;
for (int i = 59; i >= 0; i--) {
if (!son[now][(a[x] >> i) & 1]) son[now][(a[x] >> i) & 1] = ++tot;
now = son[now][(a[x] >> i) & 1];
}
id[now] = x;
}
int ask(int x) {
int now = 1;
for (int i = 59; i >= 0; i--) {
if (son[now][((a[x] >> i) & 1) ^ 1]) now = son[now][((a[x] >> i) & 1) ^ 1];
else if (son[now][((a[x] >> i) & 1)]) now = son[now][((a[x] >> i) & 1)];
else return 0;
}
return id[now];
}
void clear() {
for (int i = 1; i <= tot; i++) {
son[i][0] = son[i][1] = id[i] = 0;
}
tot = 1;
}
}
using namespace trie;
void dfs(int x) {
dep[x] = dep[fa[x]] + 1;
for (int i = h[x]; i; i = e[i].ne) {
int u = e[i].t;
dfs(u);
}
}
int p, q;
bool vis[500005];
int llc[5];
int lc;
int lca(int x, int y) {
vis[x] = true;
vis[y] = true;
if (x == y) return x;
if (dep[x] < dep[y]) swap(x, y);
while(dep[x] > dep[y]) {
x = fa[x];
vis[x] = true;
}
while(x != y) {
x = fa[x];
y = fa[y];
vis[x] = true;
vis[y] = true;
}
int ans = x;
while(x != 1) {
x = fa[x];
vis[x] = true;
}
return ans;
}
void afs(int x) {
if (!vis[x]) ans[x] = ma;
for (int i = h[x]; i; i = e[i].ne) {
int u = e[i].t;
afs(u);
}
}
long long mma;
void efs(int x) {
ins(x);
mma = max(mma, a[x] ^ a[ask(x)]);
for (int i = h[x]; i; i = e[i].ne) {
int u = e[i].t;
efs(u);
}
}
void cfs(int x, int o) {
ans[x] = mma;
ins(x);
mma = max(mma, a[x] ^ a[ask(x)]);
for (int i = h[x]; i; i = e[i].ne) {
int u = e[i].t;
if (!vis[u] || u == llc[o]) {
efs(u);
}
}
for (int i = h[x]; i; i = e[i].ne) {
int u = e[i].t;
if (vis[u] && u != llc[o]) {
cfs(u, o);
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
int x;
for (int i = 2; i <= n; i++) {
cin >> x;
fa[i] = x;
add(x, i);
}
tot = 1;
for (int i = 1; i <= n; i++) {
cin >> a[i];
ins(i);
int y = ask(i);
if ((a[i] ^ a[y]) > ma) {
ma = (a[i] ^ a[y]);
p = i;
q = y;
}
}
dfs(1);
lc = lca(p, q);
for (int i = h[lc]; i; i = e[i].ne) {
int u = e[i].t;
if (vis[u]) {
llc[1] = llc[0];
llc[0] = u;
}
}
afs(1);
clear();
cfs(1, 0);
mma = 0;
clear();
cfs(1, 1);
for (int i = 1; i <= n; i++) {
cout << ans[i] << endl;
}
return 0;
}