#include <iostream>
#include <set>
#include <vector>
using namespace std;
struct Node
{
int PrimSet = 0; // wartość i z przedziału [1, n], jeśli węzeł odpowiada podstawowemu zbiorowi Ai; 0 w p.p.
string op; // wartość pusta, jeśli PrimSet <> 0; w p.p. "U" - suma, "I" - iloczzyn, "R" - roznica
Node *LeftSet, *RightSet; // NULL jeśli PrimSet <> 0; w p.p. wskaźniki na Node'y
};
bool isInSet(int elem, Node *node, vector<set<int>> &sets)
{
struct Frame
{
Node *node;
int state; // 0 - wejście, 1 - po lewym poddrzewie, 2 - po prawym poddrzewie
bool isInLeftSet;
bool isInRightSet;
};
vector<Frame> stack;
stack.push_back({node, 0, false, false});
bool lastResult = false;
while (!stack.empty())
{
Frame &frame = stack.back();
if (frame.node->PrimSet != 0)
{
// sprawdzamy przynależność elementu elem do jednego ze zbiorów A1 ... An
lastResult = (sets[frame.node->PrimSet].find(elem) != sets[frame.node->PrimSet].end());
stack.pop_back();
}
else if (frame.state == 0)
{
// sprawdzamy przynależność elementu elem do lewego argumentu
frame.state = 1;
stack.push_back({frame.node->LeftSet, 0, false, false});
}
else if (frame.state == 1)
{
// zapamiętujemy wynik dla lewego argumentu i przechodzimy do prawego
frame.isInLeftSet = lastResult;
frame.state = 2;
stack.push_back({frame.node->RightSet, 0, false, false});
}
else
{
// łączymy wyniki dla zbiorów An+1 ... Am
frame.isInRightSet = lastResult;
if (frame.node->op == "U")
lastResult = frame.isInLeftSet || frame.isInRightSet;
else if (frame.node->op == "I")
lastResult = frame.isInLeftSet && frame.isInRightSet;
else if (frame.node->op == "R")
lastResult = frame.isInLeftSet && !frame.isInRightSet;
else
lastResult = false;
stack.pop_back();
}
}
return lastResult;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector<set<int>> S(n + 1);
// zbudowanie podzbiorów A1 ... An i wstawienie ich do wektora S
for (int i = 1; i <= n; i++)
{
for (int j = i; j <= n; j += i)
{
S[i].insert(j);
}
}
vector<Node *> A(n + m + 1);
int d, x, y;
string op;
Node *node;
// wstawienie podzbiorow A1 ... An do wektora A
for (int i = 1; i <= n; i++)
{
node = new (Node);
node->PrimSet = i;
A[i] = node;
}
// zbudowanie podzbiorów An+1 ... An+m
for (int i = 1; i <= m; i++)
{
cin >> d >> x;
if (d != 3)
{
cin >> y;
}
else
{
y = x;
x = 1;
}
switch (d)
{
case 1:
op = "U";
break;
case 2:
op = "I";
break;
case 3:
op = "R";
break;
default:
break;
}
node = new (Node);
node->op = op;
node->LeftSet = A[x];
node->RightSet = A[y];
A[n + i] = node;
}
int set, elem;
bool contains;
// pętla po pytaniach
for (int i = 0; i < q; i++)
{
cin >> set >> elem;
contains = isInSet(elem, A[set], S);
if (contains == true)
cout << "TAK\n";
else
cout << "NIE\n";
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | #include <iostream> #include <set> #include <vector> using namespace std; struct Node { int PrimSet = 0; // wartość i z przedziału [1, n], jeśli węzeł odpowiada podstawowemu zbiorowi Ai; 0 w p.p. string op; // wartość pusta, jeśli PrimSet <> 0; w p.p. "U" - suma, "I" - iloczzyn, "R" - roznica Node *LeftSet, *RightSet; // NULL jeśli PrimSet <> 0; w p.p. wskaźniki na Node'y }; bool isInSet(int elem, Node *node, vector<set<int>> &sets) { struct Frame { Node *node; int state; // 0 - wejście, 1 - po lewym poddrzewie, 2 - po prawym poddrzewie bool isInLeftSet; bool isInRightSet; }; vector<Frame> stack; stack.push_back({node, 0, false, false}); bool lastResult = false; while (!stack.empty()) { Frame &frame = stack.back(); if (frame.node->PrimSet != 0) { // sprawdzamy przynależność elementu elem do jednego ze zbiorów A1 ... An lastResult = (sets[frame.node->PrimSet].find(elem) != sets[frame.node->PrimSet].end()); stack.pop_back(); } else if (frame.state == 0) { // sprawdzamy przynależność elementu elem do lewego argumentu frame.state = 1; stack.push_back({frame.node->LeftSet, 0, false, false}); } else if (frame.state == 1) { // zapamiętujemy wynik dla lewego argumentu i przechodzimy do prawego frame.isInLeftSet = lastResult; frame.state = 2; stack.push_back({frame.node->RightSet, 0, false, false}); } else { // łączymy wyniki dla zbiorów An+1 ... Am frame.isInRightSet = lastResult; if (frame.node->op == "U") lastResult = frame.isInLeftSet || frame.isInRightSet; else if (frame.node->op == "I") lastResult = frame.isInLeftSet && frame.isInRightSet; else if (frame.node->op == "R") lastResult = frame.isInLeftSet && !frame.isInRightSet; else lastResult = false; stack.pop_back(); } } return lastResult; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n, m, q; cin >> n >> m >> q; vector<set<int>> S(n + 1); // zbudowanie podzbiorów A1 ... An i wstawienie ich do wektora S for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j += i) { S[i].insert(j); } } vector<Node *> A(n + m + 1); int d, x, y; string op; Node *node; // wstawienie podzbiorow A1 ... An do wektora A for (int i = 1; i <= n; i++) { node = new (Node); node->PrimSet = i; A[i] = node; } // zbudowanie podzbiorów An+1 ... An+m for (int i = 1; i <= m; i++) { cin >> d >> x; if (d != 3) { cin >> y; } else { y = x; x = 1; } switch (d) { case 1: op = "U"; break; case 2: op = "I"; break; case 3: op = "R"; break; default: break; } node = new (Node); node->op = op; node->LeftSet = A[x]; node->RightSet = A[y]; A[n + i] = node; } int set, elem; bool contains; // pętla po pytaniach for (int i = 0; i < q; i++) { cin >> set >> elem; contains = isInSet(elem, A[set], S); if (contains == true) cout << "TAK\n"; else cout << "NIE\n"; } return 0; } |
English