#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; } |