2020年澳门场
I题
I题是博弈(SG函数)+树形DP+树链剖分优化,
须用树链剖分的技术将
O
(
n
a
)
O(na)
O(na) 的空间复杂度优化至
O
(
a
l
o
g
(
n
)
)
O(alog(n))
O(alog(n))(不然pc上都过不了)。
转移过程类似背包,对于已存在的每一种可能,枚举放或不放,对每个点的复杂度是
O
(
a
)
O(a)
O(a)的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
const int maxn = 4e3 + 5, maxa = 1 << 8;
struct node
{
int fa;
int a;
ll b, sum;
node() { fa = -1; }
node(int a, int b, int fa) : a(a), b(b), fa(fa) {}
};
vector<node> v;
int ptr = 0;
ll dp[maxn][maxa];
void pb(int x, int y)
{
node tmp(x, y, ptr);
tmp.sum = tmp.b + v[ptr].sum;
v.push_back(tmp);
ptr = v.size() - 1;
}
void gb()
{
ptr = v[ptr].fa;
}
ll getmax(int idx)
{
if (idx == 0)
return 0;
for (int j = 0; j < maxa; ++j)
{
if (dp[v[idx].fa][j] == -1)
continue;
dp[idx][v[idx].a ^ j] = max(dp[idx][v[idx].a ^ j], dp[v[idx].fa][j] + v[idx].b);
dp[idx][j] = max(dp[idx][j], dp[v[idx].fa][j]);
}
ll ans = dp[idx][0];
ans = v[idx].sum - ans;
return ans;
}
int main()
{
// freopen("iin", "r", stdin);
scanf("%d", &n);
v.resize(1);
string s;
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i = 0, a, b; i < n; ++i)
{
cin >> s;
if (s[0] == 'A')
{
scanf("%d%d", &a, &b);
pb(a, b);
}
else
{
gb();
}
printf("%lld\n", getmax(ptr));
}
return 0;
}