#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;
const char YELLOW=1;
const char BLUE=2;
const char RED=4;
const char WIN=YELLOW | BLUE;
struct Node {
Node* left;
Node* right;
Node* parent;
/** Wartość maksymalna dla lewej części poddrzewa */
int sep;
/** Bity z kolorami dla tego węzła/liścia */
char col;
public:
Node() : left(nullptr), right(nullptr), parent(nullptr), sep(-1), col(0) {}
Node(Node* p, char c): left(nullptr), right(nullptr), parent(p), sep(-1), col(c) {}
inline bool isLeaf() const { return left== nullptr; }
void initLeaf(Node* p, char c) {
parent=p;
col=c;
sep=-1;
left= nullptr;
right= nullptr;
}
void insert(int nl, int nr, int l, int r, char c) {
if(col & c) return; // węzeł jest już tak zabarwiony w całości, więc kolor nic nie zmieni
if(isLeaf()) { // liść
int size=nr-nl+1; // rozmiar liścia
int middle=nl+(size>>1);
if(nl<l) { // trzeba podzielić z lewej
left=new Node(this, col);
right=new Node(this, col);
sep = l - 1;
if(size>4 && (abs(middle-sep)>2)) sep=middle; // dodatkowy podział w celu uniknięcia listy
} else if(nr>r) { // trzeba podzielić z prawej
left=new Node(this, col);
right=new Node(this, col);
sep=r;
if(size>4 && (abs(middle-sep)>2)) sep=middle; // dodatkowy podział w celu uniknięcia listy
} else { // pokrywa się, więc aktualizujemy kolor
if(c==RED) col=YELLOW|BLUE|RED; // czerwony psuje, więc upraszczamy
else col|=c;
return; // wychodzimy, bo dwa powyższe warunki będą normalnie przetwarzane jako węzeł
}
}
if(r<=sep) { // całość po lewej
left->insert(nl, sep, l, r, c);
} else if(l>sep) { // całość po prawej
right->insert(sep+1, nr, l, r, c);
} else { // po obu stronach
left->insert(nl, sep, l, sep, c);
right->insert(sep+1, nr, sep+1, r, c);
}
if(left->col==right->col && left->isLeaf() && right->isLeaf()) { // liście mają ten sam kolor, można złączyć
col=left->col;
delete left;
delete right;
left= nullptr;
right= nullptr;
sep=-1;
} else {
col = left->col & right->col;
}
}
int count(int nl, int nr) {
if(isLeaf()) {
if(col==WIN) return nr-nl+1;
return 0;
}
return left->count(nl, sep) + right->count(sep+1, nr);
}
};
class Tree {
private:
const int n;
Node* root;
public:
Tree(int n) : n(n) {
root=new Node();
}
public:
void process(int l, int r, char col) {
root->insert(1, n, l, r, col);
}
int count() {
return root->count(1, n);
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin>>n>>m;
Tree tree(n);
for(int i=0;i<m;++i) {
int l, r, c;
cin>>l>>r>>c;
tree.process(l, r, c==1?YELLOW:(c==2?BLUE:RED));
}
cout<<tree.count()<<endl;
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 | #include <iostream> #include <map> #include <vector> #include <string> using namespace std; const char YELLOW=1; const char BLUE=2; const char RED=4; const char WIN=YELLOW | BLUE; struct Node { Node* left; Node* right; Node* parent; /** Wartość maksymalna dla lewej części poddrzewa */ int sep; /** Bity z kolorami dla tego węzła/liścia */ char col; public: Node() : left(nullptr), right(nullptr), parent(nullptr), sep(-1), col(0) {} Node(Node* p, char c): left(nullptr), right(nullptr), parent(p), sep(-1), col(c) {} inline bool isLeaf() const { return left== nullptr; } void initLeaf(Node* p, char c) { parent=p; col=c; sep=-1; left= nullptr; right= nullptr; } void insert(int nl, int nr, int l, int r, char c) { if(col & c) return; // węzeł jest już tak zabarwiony w całości, więc kolor nic nie zmieni if(isLeaf()) { // liść int size=nr-nl+1; // rozmiar liścia int middle=nl+(size>>1); if(nl<l) { // trzeba podzielić z lewej left=new Node(this, col); right=new Node(this, col); sep = l - 1; if(size>4 && (abs(middle-sep)>2)) sep=middle; // dodatkowy podział w celu uniknięcia listy } else if(nr>r) { // trzeba podzielić z prawej left=new Node(this, col); right=new Node(this, col); sep=r; if(size>4 && (abs(middle-sep)>2)) sep=middle; // dodatkowy podział w celu uniknięcia listy } else { // pokrywa się, więc aktualizujemy kolor if(c==RED) col=YELLOW|BLUE|RED; // czerwony psuje, więc upraszczamy else col|=c; return; // wychodzimy, bo dwa powyższe warunki będą normalnie przetwarzane jako węzeł } } if(r<=sep) { // całość po lewej left->insert(nl, sep, l, r, c); } else if(l>sep) { // całość po prawej right->insert(sep+1, nr, l, r, c); } else { // po obu stronach left->insert(nl, sep, l, sep, c); right->insert(sep+1, nr, sep+1, r, c); } if(left->col==right->col && left->isLeaf() && right->isLeaf()) { // liście mają ten sam kolor, można złączyć col=left->col; delete left; delete right; left= nullptr; right= nullptr; sep=-1; } else { col = left->col & right->col; } } int count(int nl, int nr) { if(isLeaf()) { if(col==WIN) return nr-nl+1; return 0; } return left->count(nl, sep) + right->count(sep+1, nr); } }; class Tree { private: const int n; Node* root; public: Tree(int n) : n(n) { root=new Node(); } public: void process(int l, int r, char col) { root->insert(1, n, l, r, col); } int count() { return root->count(1, n); } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin>>n>>m; Tree tree(n); for(int i=0;i<m;++i) { int l, r, c; cin>>l>>r>>c; tree.process(l, r, c==1?YELLOW:(c==2?BLUE:RED)); } cout<<tree.count()<<endl; return 0; } |
English