Title Link: cf-r296-d2-d
Main topic
A special graph, some points on the axis, each point has a coordinate X, there is a weight of W, two points (I, J) have an edge between and only if | xi-xj| >= Wi + Wj.
Ask for the largest regiment of this figure.
The number of points in the graph N <= 10^5.
Problem analysis
Two points right between meet Xj-xi >= Wi + Wj (xi < XJ) ==> XJ-WJ >= Xi + Wi (xi < XJ)
Sort by coordinates x from small to general points. Use f[i] to indicate the maximum group size of the first I point.
Then f[i] = max (f[k]) + 1 (k < i && (xi-wi >= Xk + Wk))
This prefix maximum value query is implemented by the segment tree, and then the f[i] is also stored in the Xi + Wi of the line segment tree.
Code
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath > #include <algorithm>using namespace std;const int maxn = 200000 + 5, Maxnode = 200000 * + +, INF = 100000000 0;int N, Index, Root, Ans;int T[maxnode], son[maxnode][2];struct es{int x, W;bool operator < (const ES b) Const{return x < b.x;}} e[maxn];inline int gmax (int a, int b) {return a > B? a:b;} void Set_max (int &x, int s, int t, int Pos, int Num) {if (x = = 0) x = ++index; T[X] = Gmax (t[x], num), if (s = = t) return;int m = (s + t) >> 1;if (pos <= m) Set_max (Son[x][0], S, M, Pos, Num); E LSE Set_max (Son[x][1], M + 1, T, Pos, Num);} int Get_max (int x, int s, int t, int r) {if (R >= t) return t[x];int m = (s + t) >> 1;int Ret;ret = Get_max (Son[x] [0], S, M, R), if (R >= m + 1) ret = Gmax (ret, Get_max (son[x][1], M + 1, T, R)); return ret;} int main () {scanf ("%d", &n), for (int i = 1; I <= n; ++i) scanf ("%d%d", &e[i].x, &E[I].W); sort (e + 1, e + n + 1); Ans = 0;index = 0;int T, fi;for (int i = 1; I <= n; ++i) {t = e[i].x-e[i].w;if (i! = 1) Fi = Get_max (Root,-inf, INF, T) + 1;else Fi = 1;if (Fi > ans) Ans = fi;t = e[i].x + e[i].w; Set_max (Root,-inf, INF, T, Fi); }printf ("%d\n", Ans); return 0;}
[Codeforces Round #296 div2 D] Clique problem "segment Tree +DP"