洛谷民间数据 AC,官方数据 50pts(WA+TLE)。
不清楚这个做法为什么能拿到分,也不知道为什么会 WA 和 TLE。
自己测试的时候感觉只要 limbo iteration 迭代次数足够多,就能抛出一个正确的结果,然而似乎并不是这样(
思路和一些细节都在注释里了。
#include <iostream>
#include <numeric>
#include <syncstream>
#include <vector>
using namespace std;
constexpr int VT_T = 0xf4240;
constexpr int VT_F = 0xf4241;
constexpr int VT_U = 0xf4242;
// specifications:
// 1: x_1 initial value
// 2: x_2 initial value
// -3: negation x_3
// --5 is folded to 5
// ---6 is folded to -6
// VT_T is T
// VT_F is F
// VT_U is U
// fin
inline int flip(int a)
{
if (a == VT_T) {
return VT_F;
}
if (a == VT_F) {
return VT_T;
}
if (a == VT_U) {
return VT_U;
}
return -a;
}
// clang-tidy says:
// Function 'tmain' has cognitive complexity of 37 (threshold 25) [readability-function-cognitive-complexity]
// agree
void tmain()
{
vector<int> vec; // variables, see specifications for value meaning
vector<tuple<char, int, int>> ops; // statements
int n, m;
cin >> n >> m;
vec.resize(n);
iota(vec.begin(), vec.end(), 1); // initalize variables with their own initial values
for (int i = 0; i < m; ++i) {
char op;
int x, y;
cin >> op >> x;
if (op == 'T') {
vec[x - 1] = VT_T;
} else if (op == 'F') {
vec[x - 1] = VT_F;
} else if (op == 'U') {
vec[x - 1] = VT_U;
} else if (op == '+') {
cin >> y;
vec[x - 1] = vec[y - 1];
} else if (op == '-') {
cin >> y;
vec[x - 1] = flip(vec[y - 1]);
}
ops.emplace_back(op, x, y);
}
// a limbo variable is a reference to a variable's inital variable
// such as 1, -2
// not VT_T, VT_F, VT_U
int lastlimbos{}; // last limbo count
int inertia = 10; // iteration inertia, just like SA's temperature
for (auto i : vec) {
// cout << i << ' ';
if (i <= n) {
++lastlimbos;
}
}
// cout << endl;
// limbo iteration
for (int k = 0; k < 2000; ++k) { // breaker at 2000 iterations
int limbos{};
// resolve unknown variables
// if a variable's value is negative of its initial value after running the statements
// then it's initial value must be unknown
for (int i = 0; i < n; ++i) {
if (vec[i] == -(i + 1)) {
vec[i] = VT_U;
}
}
// execute statements
for (auto [v, x, y] : ops) {
if (v == 'T') {
vec[x - 1] = VT_T;
} else if (v == 'F') {
vec[x - 1] = VT_F;
} else if (v == 'U') {
vec[x - 1] = VT_U;
} else if (v == '+') {
vec[x - 1] = vec[y - 1];
} else if (v == '-') {
vec[x - 1] = flip(vec[y - 1]);
}
}
for (auto i : vec) {
// cout << i << ' ';
if (i <= n) {
++limbos;
}
}
// cout << endl;
if (limbos < lastlimbos) {
lastlimbos = limbos;
++inertia; // boost velocity, more inertia
continue; // remove this line if you want no velocity boost
}
if (inertia == 0) {
break; // stopped
}
--inertia;
}
int ans{};
for (auto i : vec) {
if (i == VT_U) {
++ans;
}
}
cout << ans << '\n';
}
// never mind this, but if you really care it:
//
// Synchronizes the output of std::cout by redirecting it to a synchronized buffer.
[[gnu::constructor]] void syncio_routine()
{
static syncbuf sbuf{cout.rdbuf()};
cout.rdbuf(&sbuf);
}
int main()
{
int c, t;
cin >> c >> t;
for (int i = 0; i < t; ++i) {
tmain();
}
return 0;
}