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

线段树分治+线性基。

其实如果想到了就比较好写了。

但是复杂度很迷啊。

T-34

#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;
}
posted @ 2024-01-30 22:01  觉清风  阅读(24)  评论(0编辑  收藏  举报