Codeforces 1462F. The Treasure of The Segments (greedy & tree array)

F. The Treasure of The Segments

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Polycarp found nn segments on the street. A segment with the index ii is described by two integers lili and riri — coordinates of the beginning and end of the segment, respectively. Polycarp realized that he didn't need all the segments, so he wanted to delete some of them.

Polycarp believes that a set of kk segments is good if there is a segment [li,ri][li,ri] (1≤i≤k1≤i≤k) from the set, such that it intersects every segment from the set (the intersection must be a point or segment). For example, a set of 33 segments [[1,4],[2,3],[3,6]][[1,4],[2,3],[3,6]] is good, since the segment [2,3][2,3] intersects each segment from the set. Set of 44 segments [[1,2],[2,3],[3,5],[4,5]][[1,2],[2,3],[3,5],[4,5]] is not good.

Polycarp wonders, what is the minimum number of segments he has to delete so that the remaining segments form a good set?

Input

The first line contains a single integer tt (1≤t≤2⋅1051≤t≤2⋅105) — number of test cases. Then tt test cases follow.

The first line of each test case contains a single integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of segments. This is followed by nn lines describing the segments.

Each segment is described by two integers ll and rr (1≤l≤r≤1091≤l≤r≤109) — coordinates of the beginning and end of the segment, respectively.

It is guaranteed that the sum of nn for all test cases does not exceed 2⋅1052⋅105.

Output

For each test case, output a single integer — the minimum number of segments that need to be deleted in order for the set of remaining segments to become good.

Example

input

Copy

4
3
1 4
2 3
3 6
4
1 2
2 3
3 5
4 5
5
1 2
3 8
4 5
6 7
9 10
5
1 5
2 4
3 5
3 8
4 8

output

Copy

0
1
2
0

Main idea:

There are N line segments, a line segment set is good, if and only if there is at least one line segment in the set that can intersect all the line segments in the set, now let you delete the fewest line segments so that the remaining line segments can form a good set. Output the minimum number of deletions.

solution:

The question is transformed into asking you how many line segments intersect each line segment.

First of all discretize, we only look at the endpoints of each line segment. For a certain line segment, how many endpoints appear in the interval represents how many intersecting line segments. Note that if both endpoints of a certain line segment are inside, the answer is wrong , so we need For classification, add the left end point first, and then add the right end point. At this time, the idea has come out. According to the order of the left and right endpoints, first visit how many left endpoints each line segment contains, and then traverse backwards to see how many right endpoints are included, and maintain it with a tree array in the middle.

Accepted code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 2e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

struct node
{
	int l, r;
	bool operator < (const node &oth) const {
		if (r == oth.r)
			return l < oth.l;
		else
			return r < oth.r;
	}
}a[N];
int s[N * 2], ans[N], n, sz;
vector <int> ver;

void Init() {
	for (int i = 1; i <= sz; i++)
		s[i] = 0;
	ver.clear();
}
void Add(int x, int v) {
	while (x <= sz)
		s[x] += v, x += lowbit(x);
}
int Ask(int x) {
	int tot = 0;
	while (x)
		tot += s[x], x -= lowbit(x);
	return tot;
}
int Rg_Ask(int l, int r) {
	return Ask(r) - Ask(l - 1); 
}

int main()
{
#ifdef OlaMins
	freopen("D:/input.txt", "r", stdin);
	//freopen("D:/output.txt", "w", stdout);
#endif

	int T; cin >> T;
	while (T--) {
		sc("%d", &n);
		Init();

		for (int i = 1; i <= n; i++) {
			int l, r;
			sc("%d %d", &l, &r);
			ver.push_back(l), ver.push_back(r);
			a[i] = { l, r }, ans[i] = 0;
		}
		sort(ALL(ver));
		ver.erase(unique(ALL(ver)), ver.end());  // 离散化
		sz = SZ(ver);

		for (int i = 1; i <= n; i++) {
			a[i].l = lower_bound(ALL(ver), a[i].l) - ver.begin() + 1;
			a[i].r = lower_bound(ALL(ver), a[i].r) - ver.begin() + 1;
		}
		sort(a + 1, a + n + 1);

		for (int i = 1; i <= n; i++) {  // 先左
			int l = a[i].l, r = a[i].r;
			ans[i] = Rg_Ask(l, r);
			Add(r, 1);
		}

		for (int i = 1; i <= sz; i++)
			s[i] = 0;
		int mi = INF;
		for (int i = n; i >= 1; i--) {   // 后右
			int l = a[i].l, r = a[i].r;
			ans[i] += Rg_Ask(l, r);
			Min(mi, n - ans[i]);
			Add(l, 1);
		}
		printf("%d\n", mi - 1);
	}
	return 0; // 改数组大小!!!用pair改宏定义!!!
}

 

Guess you like

Origin blog.csdn.net/weixin_43851525/article/details/111384943