// PA2014, runda 5, Plemiona // Andrzej Pezarski #include <cstdio> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> #include <algorithm> using namespace std; int N, L; bool odwroc; priority_queue<pair<int, int> > Q; vector<int> X, Y; vector<pair<pair<int, int>,pair<int, int> > > P; vector<bool> taken; vector<set<pair<int, int> > > A, B; inline void doCheck(set<pair<int, int> > &S, vector<int> &Res, pair<int, int> x) { auto tmp1=make_pair(1+2*x.first, -10000000); auto tmp2=make_pair(2*x.second, -10000000); for (auto it=S.lower_bound(tmp1), end=S.lower_bound(tmp2); it!=end; ++it) { // printf("tutaj\n"); if (taken[it->second]) { Res.push_back(it->second); taken[it->second]=false; } } } vector<int> check(pair<int, int> x, pair<int, int> y) { vector<int> Res; int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doCheck(A[l], Res, x); doCheck(A[r], Res, x); doCheck(B[l], Res, x); doCheck(B[r], Res, x); while(l/2!=r/2) { if (l%2==0) { doCheck(A[l+1], Res, x); doCheck(B[l+1], Res, x); } if (r%2==1) { doCheck(A[r-1], Res, x); doCheck(B[r-1], Res, x); } l/=2; r/=2; doCheck(A[l], Res, x); doCheck(A[r], Res, x); } while(l>1) { l/=2; doCheck(A[l], Res, x); } return Res; } inline void doWsadz(set<pair<int, int> > &S, pair<int, int> x, int v) { S.insert(make_pair(1+2*x.first, v)); S.insert(make_pair(2*x.second, v)); } void wsadz(pair<int, int> x, pair<int, int> y, int v) { int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doWsadz(A[l], x, v); doWsadz(A[r], x, v); // doWsadz(B[l], x, v); // doWsadz(B[r], x, v); while(l/2!=r/2) { if (l%2==0) { doWsadz(A[l+1], x, v); // doWsadz(B[l+1], x, v); } if (r%2==1) { doWsadz(A[r-1], x, v); // doWsadz(B[r-1], x, v); } l/=2; r/=2; doWsadz(B[l], x, v); doWsadz(B[r], x, v); } while(l>1) { l/=2; doWsadz(B[l], x, v); } } inline void doUsun(set<pair<int, int> > &S, pair<int, int> x, int v) { S.erase(make_pair(1+2*x.first, v)); S.erase(make_pair(2*x.second, v)); } void usun(pair<int, int> x, pair<int, int> y, int v) { int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doUsun(A[l], x, v); doUsun(A[r], x, v); // doUsun(B[l], x, v); // doUsun(B[r], x, v); while(l/2!=r/2) { if (l%2==0) { doUsun(A[l+1], x, v); // doUsun(B[l+1], x, v); } if (r%2==1) { doUsun(A[r-1], x, v); // doUsun(B[r-1], x, v); } l/=2; r/=2; doUsun(B[l], x, v); doUsun(B[r], x, v); } while(l>1) { l/=2; doUsun(B[l], x, v); } } int main() { //INPUT scanf("%d", &N); P.resize(N); taken.resize(N); for(int i=0; i<N; i++) taken[i]=false; for(auto &p:P) { scanf("%d%d%d%d", &p.first.first, &p.first.second, &p.second.first, &p.second.second); X.push_back(p.first.first); X.push_back(p.first.second); Y.push_back(p.second.first); Y.push_back(p.second.second); } sort(X.begin(), X.end()); X.resize(unique(X.begin(), X.end())-X.begin()); sort(Y.begin(), Y.end()); Y.resize(unique(Y.begin(), Y.end())-Y.begin()); odwroc=(X.size()<Y.size()); if(odwroc) { X.swap(Y); for(auto &p:P) swap(p.first, p.second); } L=1; while (L<=int(Y.size())) L*=2; A.resize(2*L); B.resize(2*L); // GO for (int i=0; i<N; i++) Q.push(make_pair(P[i].first.first-P[i].first.second, i)); while (!Q.empty()) { int v=Q.top().second; Q.pop(); auto X=check(P[v].first, P[v].second); if (X.empty()) { wsadz(P[v].first, P[v].second, v); taken[v]=true; } else { int x1=P[v].first.first, x2=P[v].first.second, y1=P[v].second.first, y2=P[v].second.second; for (auto x:X) { x1=min(x1, P[x].first.first); x2=max(x2, P[x].first.second); y1=min(y1, P[x].second.first); y2=max(y2, P[x].second.second); usun(P[x].first, P[x].second, x); taken[x]=false; } P[v].first.first=x1, P[v].first.second=x2, P[v].second.first=y1, P[v].second.second=y2; Q.push(make_pair(P[v].first.first-P[v].first.second, v)); } } // OUTPUT vector<pair<pair<int, int>,pair<int, int> > > Res; for(int i=0; i<N; i++) { if (taken[i]) { Res.push_back(P[i]); } } if (odwroc) { for(auto &p:Res) swap(p.first, p.second); } sort(Res.begin(), Res.end()); printf("%d\n", int(Res.size())); for(auto &p:Res) { printf("%d %d %d %d\n", p.first.first, p.first.second, p.second.first, p.second.second); } 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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | // PA2014, runda 5, Plemiona // Andrzej Pezarski #include <cstdio> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> #include <algorithm> using namespace std; int N, L; bool odwroc; priority_queue<pair<int, int> > Q; vector<int> X, Y; vector<pair<pair<int, int>,pair<int, int> > > P; vector<bool> taken; vector<set<pair<int, int> > > A, B; inline void doCheck(set<pair<int, int> > &S, vector<int> &Res, pair<int, int> x) { auto tmp1=make_pair(1+2*x.first, -10000000); auto tmp2=make_pair(2*x.second, -10000000); for (auto it=S.lower_bound(tmp1), end=S.lower_bound(tmp2); it!=end; ++it) { // printf("tutaj\n"); if (taken[it->second]) { Res.push_back(it->second); taken[it->second]=false; } } } vector<int> check(pair<int, int> x, pair<int, int> y) { vector<int> Res; int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doCheck(A[l], Res, x); doCheck(A[r], Res, x); doCheck(B[l], Res, x); doCheck(B[r], Res, x); while(l/2!=r/2) { if (l%2==0) { doCheck(A[l+1], Res, x); doCheck(B[l+1], Res, x); } if (r%2==1) { doCheck(A[r-1], Res, x); doCheck(B[r-1], Res, x); } l/=2; r/=2; doCheck(A[l], Res, x); doCheck(A[r], Res, x); } while(l>1) { l/=2; doCheck(A[l], Res, x); } return Res; } inline void doWsadz(set<pair<int, int> > &S, pair<int, int> x, int v) { S.insert(make_pair(1+2*x.first, v)); S.insert(make_pair(2*x.second, v)); } void wsadz(pair<int, int> x, pair<int, int> y, int v) { int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doWsadz(A[l], x, v); doWsadz(A[r], x, v); // doWsadz(B[l], x, v); // doWsadz(B[r], x, v); while(l/2!=r/2) { if (l%2==0) { doWsadz(A[l+1], x, v); // doWsadz(B[l+1], x, v); } if (r%2==1) { doWsadz(A[r-1], x, v); // doWsadz(B[r-1], x, v); } l/=2; r/=2; doWsadz(B[l], x, v); doWsadz(B[r], x, v); } while(l>1) { l/=2; doWsadz(B[l], x, v); } } inline void doUsun(set<pair<int, int> > &S, pair<int, int> x, int v) { S.erase(make_pair(1+2*x.first, v)); S.erase(make_pair(2*x.second, v)); } void usun(pair<int, int> x, pair<int, int> y, int v) { int l=lower_bound(Y.begin(), Y.end(), y.first)-Y.begin()+L; int r=lower_bound(Y.begin(), Y.end(), y.second)-Y.begin()+L-1; doUsun(A[l], x, v); doUsun(A[r], x, v); // doUsun(B[l], x, v); // doUsun(B[r], x, v); while(l/2!=r/2) { if (l%2==0) { doUsun(A[l+1], x, v); // doUsun(B[l+1], x, v); } if (r%2==1) { doUsun(A[r-1], x, v); // doUsun(B[r-1], x, v); } l/=2; r/=2; doUsun(B[l], x, v); doUsun(B[r], x, v); } while(l>1) { l/=2; doUsun(B[l], x, v); } } int main() { //INPUT scanf("%d", &N); P.resize(N); taken.resize(N); for(int i=0; i<N; i++) taken[i]=false; for(auto &p:P) { scanf("%d%d%d%d", &p.first.first, &p.first.second, &p.second.first, &p.second.second); X.push_back(p.first.first); X.push_back(p.first.second); Y.push_back(p.second.first); Y.push_back(p.second.second); } sort(X.begin(), X.end()); X.resize(unique(X.begin(), X.end())-X.begin()); sort(Y.begin(), Y.end()); Y.resize(unique(Y.begin(), Y.end())-Y.begin()); odwroc=(X.size()<Y.size()); if(odwroc) { X.swap(Y); for(auto &p:P) swap(p.first, p.second); } L=1; while (L<=int(Y.size())) L*=2; A.resize(2*L); B.resize(2*L); // GO for (int i=0; i<N; i++) Q.push(make_pair(P[i].first.first-P[i].first.second, i)); while (!Q.empty()) { int v=Q.top().second; Q.pop(); auto X=check(P[v].first, P[v].second); if (X.empty()) { wsadz(P[v].first, P[v].second, v); taken[v]=true; } else { int x1=P[v].first.first, x2=P[v].first.second, y1=P[v].second.first, y2=P[v].second.second; for (auto x:X) { x1=min(x1, P[x].first.first); x2=max(x2, P[x].first.second); y1=min(y1, P[x].second.first); y2=max(y2, P[x].second.second); usun(P[x].first, P[x].second, x); taken[x]=false; } P[v].first.first=x1, P[v].first.second=x2, P[v].second.first=y1, P[v].second.second=y2; Q.push(make_pair(P[v].first.first-P[v].first.second, v)); } } // OUTPUT vector<pair<pair<int, int>,pair<int, int> > > Res; for(int i=0; i<N; i++) { if (taken[i]) { Res.push_back(P[i]); } } if (odwroc) { for(auto &p:Res) swap(p.first, p.second); } sort(Res.begin(), Res.end()); printf("%d\n", int(Res.size())); for(auto &p:Res) { printf("%d %d %d %d\n", p.first.first, p.first.second, p.second.first, p.second.second); } return 0; } |