2024.1.30做题纪要
[bzoj3569]DZY Loves Chinese II
第一眼:这和线性基有什么关系。。。
第二眼:这到底跟线性基有什么关系???
对于一个图,我们先想建树,然后加返祖边。
我们考虑一下对于一个点什么情况才会出现不连通的情况???当连接这个点的树边和跨过这个点的非树边都断开时不连通。
那我们怎么判断是不是都断开了???异或为零!!!我们将非树边rand一个值,然后树边的权值是跨过这条边的非树边的异或和就行了。
至于非树边的贡献则是用差分就行了
谢尔曼M1
#include <bits/stdc++.h>
const int SIZE = 5e5 + 10;
int cnt = 1, head[SIZE], next[SIZE * 2], to[SIZE * 2], rank[SIZE * 2];
void AddEdge(int u, int v, int rnk) {
++ cnt;
next[cnt] = head[u];
head[u] = cnt;
to[cnt] = v;
rank[cnt] = rnk;
}
int xorSum[SIZE], value[SIZE], fat[SIZE];
bool flag[SIZE * 2], visit[SIZE];
void Dfs(int now, int fa) {
fat[now] = fa;
visit[now] = true;
for (int i = head[now]; i; i = next[i]) {
if (flag[i])
continue;
flag[i] = flag[i ^ 1] = true;
if (visit[to[i]]) {
value[rank[i]] = rand() % (1000000000) + 1;
xorSum[now] ^= value[rank[i]];
xorSum[to[i]] ^= value[rank[i]];
}
else {
Dfs(to[i], now);
xorSum[now] ^= xorSum[to[i]];
value[rank[i]] = xorSum[to[i]];
}
}
}
class LinearBasis {
private:
int cnt, bit[50];
public:
void clear() {
for (int i = 0; i <= 32; ++ i)
bit[i] = 0;
}
bool Insert(int x) {
for (int i = 31; i >= 0; -- i) {
if (x & (1 << i)) {
if (bit[i]) {
x ^= bit[i];
}
else {
bit[i] = x;
return false;
}
}
}
return true;
}
}basis;
int N, M, Q, answer;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> N >> M;
for (int i = 1, u, v; i <= M; ++ i) {
std::cin >> u >> v;
AddEdge(u, v, i);
AddEdge(v, u, i);
}
Dfs(1, 0);
std::cin >> Q;
for (int i = 1, K; i <= Q; ++ i) {
basis.clear();
std::cin >> K;
bool result = false;
for (int j = 1, x; j <= K; ++ j) {
std::cin >> x;
x ^= answer;
result |= basis.Insert(value[x]);
}
answer += !result;
if (!result)
std::cout << "Connected\n";
else
std::cout << "Disconnected\n";
}
return 0;
}
shallot
线段树分治+线性基。
其实如果想到了就比较好写了。
但是复杂度很迷啊。
#include <bits/stdc++.h>
const int SIZE = 5e5 + 10;
class LinearBasis {
private:
int cnt, bit[31];
public:
void Insert(int x) {
for (int i = 30; i >= 0; -- i) {
if (x & (1 << i)) {
if (bit[i]) {
x ^= bit[i];
}
else {
bit[i] = x;
return;
}
}
}
}
int QueryMax() {
int result = 0;
for (int i = 30; i >= 0; -- i)
if ((result ^ bit[i]) > result)
result = result ^ bit[i];
return result;
}
}basis[30];
class SegmentTree {
#define lid (id << 1)
#define rid (id << 1 | 1)
public:
std::vector<int> barrel[SIZE * 4];
void Update(int id, int l, int r, int askL, int askR, int number) {
if (askL <= l && r <= askR) {
barrel[id].emplace_back(number);
return;
}
int mid = (l + r) >> 1;
if (askL <= mid)
Update(lid, l, mid, askL, askR, number);
if (mid + 1 <= askR)
Update(rid, mid + 1, r, askL, askR, number);
return;
}
void Solve(int id, int l, int r, int deep) {
basis[deep] = basis[deep - 1];
for (const int &iter: barrel[id]) {
basis[deep].Insert(iter);
}
if (l == r) {
std::cout << basis[deep].QueryMax() << '\n';
return;
}
int mid = (l + r) >> 1;
Solve(lid, l, mid, deep + 1);
Solve(rid, mid + 1, r, deep + 1);
}
}tree;
int N;
std::map<int, std::pair<int, int>> map;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> N;
for (int i = 1, x; i <= N; ++ i) {
std::cin >> x;
if (x < 0) {
x = -x;
map[x].second = i - 1;
}
else {
map[x] = std::make_pair(i, N);
}
}
for (const std::pair<int, std::pair<int, int>> &iter: map) {
tree.Update(1, 1, N, iter.second.first, iter.second.second, iter.first);
}
tree.Solve(1, 1, N, 1);
return 0;
}
幸运数字
这道题数据水,为什么3log能过?????????
题解可以看洛谷
虎Ⅰ
#include <bits/stdc++.h>
typedef long long ll;
const int SIZE = 2e4 + 10;
class LinearBasis {
private:
int cnt, deep[61];
ll bit[60];
public:
friend ll Answer(LinearBasis &a, LinearBasis &b, int minDeep);
void Insert(int dep, ll x) {
for (int i = 60; i >= 0; -- i) {
if (x & (1ll << i)) {
if (bit[i]) {
if (deep[i] < dep) {
std::swap(deep[i], dep);
std::swap(bit[i], x);
}
x ^= bit[i];
}
else {
bit[i] = x;
deep[i] = dep;
return;
}
}
}
}
}basis[SIZE], temp;
int cnt = 1, head[SIZE], next[SIZE * 2], to[SIZE * 2];
void AddEdge(int u, int v) {
++ cnt;
next[cnt] = head[u];
head[u] = cnt;
to[cnt] = v;
}
int N, Q;
ll value[SIZE];
int fat[SIZE][20], deep[SIZE];
void Dfs(int now, int fa) {
deep[now] = deep[fa] + 1;
fat[now][0] = fa;
for (int i = 1; i <= 19; ++ i) {
fat[now][i] = fat[fat[now][i - 1]][i - 1];
if (!fat[now][i])
break;
}
basis[now] = basis[fa];
basis[now].Insert(deep[now], value[now]);
for (int i = head[now]; i; i = next[i]) {
if (to[i] == fa)
continue;
Dfs(to[i], now);
}
}
int GetLca(int x, int y) {
if (deep[x] < deep[y])
std::swap(x, y);
for (int i = 19; i >= 0; -- i)
if (deep[fat[x][i]] >= deep[y])
x = fat[x][i];
if (x == y)
return x;
for (int i = 19; i >= 0; -- i) {
if (fat[x][i] != fat[y][i]) {
x = fat[x][i];
y = fat[y][i];
}
}
return fat[x][0];
}
ll Answer(LinearBasis &a, LinearBasis &b, int minDeep) {
ll result = 0;
temp = a;
for (int i = 60; i >= 0; -- i)
temp.Insert(b.deep[i], b.bit[i]);
for (int i = 60; i >= 0; -- i) {
if (temp.deep[i] >= minDeep)
result = std::max(result, result ^ temp.bit[i]);
}
return result;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> N >> Q;
for (int i = 1; i <= N; ++ i)
std::cin >> value[i];
for (int i = 1, u, v; i <= N - 1; ++ i) {
std::cin >> u >> v;
AddEdge(u, v);
AddEdge(v, u);
}
Dfs(1, 0);
for (int i = 1, x, y, lca; i <= Q; ++ i) {
std::cin >> x >> y;
lca = GetLca(x, y);
std::cout << Answer(basis[x], basis[y], deep[lca]) << '\n';
}
return 0;
}