题意:给1棵N(≤500,000)个节点的树,每条边边权为1,求距离每个点距离不超过K(K≤10)的点的个数的xor和。
思路:由于K很小,可以考虑把距离作为状态的一部分,然后研究父子之间状态的联系。令ans[i][j]表示与i的距离为j的点的个数,那么ans[i][j]由两部分构成,一部分来源于子树,一部分来源于父亲,那么令f[i][j]表示从子树来的答案,g[i][j]表示从父亲来的答案,son(i)表示i的儿子,fa(i)表示i的父亲,则有:
ans[i][j] = f[i][j] + g[i][j]
f[i][j] = ∑f[son(i)][j-1]
g[i][j] = ans[fa(i)][j-1] - f[i][j-2]
具体做法是:先自底向上求解f数组,这里可以利用队列按拓扑序依次访问每个点,然后自顶向下求g数组,这时只要在上一步的队列里面逆着扫一遍就行了。由于没有递归,速度还是非常快的,把上面的g和ans省掉后,以200ms的速度排到了rank1,小小激动了一下=.=
#include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE #include "local.h" #endif #define pb(x) push_back(x) #define mp(x, y) make_pair(x, y) #define all(a) (a).begin(), (a).end() #define watch(ele) cout << ele << endl; #define mset(a, x) memset(a, x, sizeof(a)) #define mcpy(a, b) memcpy(a, b, sizeof(b)) #define up(a, b) for (int a = 0; a < b; a ++) #define up1(a, b) for (int a = 1; a <= b; a ++) #define down1(a, b) for (int a = b; a >= 1; a --) #define rep(i, a, b) for (int i = a; i <= b; i ++) #define rrep(i, a, b) for (int i = a; i >= b; i --) #define down(a, b) for (int a = b - 1; a >= 0; a --) #define cas() int T, cas = 0; cin >> T; while (T --) #define printCas(ch) printf("Case #%d:%c", ++ cas, ch) typedef long long ll; typedef pair<int, int> pii; template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;} template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;} const int N = 5e5 + 7; int n, k, a, b; int din[N], fa[N], f[N][11]; void getData() { mset(din, 0); fa[1] = 0; rep(i, 2, n) { int f = ((ll)a * i + b) % (i - 1) + 1; din[f] ++; fa[i] = f; } } int Q[N], head, tail; void work() { head = tail = 0; mset(f, 0); up1(i, n) if (din[i] == 0) Q[tail ++] = i; up1(i, n) f[i][0] = 1; while (head < tail) { int node = Q[head ++]; up(i, k) f[fa[node]][i + 1] += f[node][i]; if (-- din[fa[node]] == 0) Q[tail ++] = fa[node]; } int apple = 0; rrep(i, tail - 1, 0) { int node = Q[i]; if (fa[node]) rrep(j, k, 1) f[node][j] += f[fa[node]][j - 1] - (j >= 2?f[node][j - 2] : 0); int buf = 0; rep(j, 0, k) buf += f[node][j]; apple ^= buf; } cout << apple << endl; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGE cas() { cin >> n >> k >> a >> b; getData(); work(); } return 0; }