Problem - F - CodeforcesF. 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
=========================================================================
直接考虑On暴力求解, 可以知道的是,我们枚举每个小区间,就能确定全部与之相交的区间个数。那么考虑如何涉及这一算法,考虑左端点从小到大排序,那么对于排在当前区间前面的,其左端点都小于等于他,我们再只需要满足左端点小于等于右端点即可保证相交,对于排在其后面的,左端点大于等于本位置左端点,我们只需要保证本位置右端点大于等于其左端点即可。那么我们可以用两个树状数组,对于“ 左端点小于等于右端点即可保证相交 ” 这一条件,构造前缀树状数组,并依次添加,对于 “本位置右端点大于等于其左端点即可” 这一条件,事先构造后缀树状数组,并依次减少即可。
另外用到了离散化技巧,把左右端点全部加入离散集合。且查询大于等于一个值的时候,考虑将下标赋值为 n-pos+1,倒序存储。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
struct node
{
int l,r;
};
struct node s[200000+10];
bool cmp(struct node x, struct node y)
{
if(x.l!=y.l)
return x.l<y.l;
return x.r>y.r;
}
int myhash[400000+10],sum1[400000+10],sum2[400000+10];
int lowbit(int x)
{
return x&-x;
}
int getsum1(int x)
{
int ans=0;
while(x)
{
ans+=sum1[x];
x-=lowbit(x);
}
return ans;
}
int getsum2(int x)
{
int ans=0;
while(x)
{
ans+=sum2[x];
x-=lowbit(x);
}
return ans;
}
void change1(int x,int val)
{
while(x<=400000)
{
sum1[x]+=val;
x+=lowbit(x);
}
}
void change2(int x,int val)
{
while(x<=400000)
{
sum2[x]+=val;
x+=lowbit(x);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i].l>>s[i].r;
myhash[i]=s[i].r;
myhash[i+n]=s[i].l;
sum1[i]=sum1[i+n]=sum2[i]=sum2[i+n]=0;
}
sort(myhash+1,myhash+1+2*n);
sort(s+1,s+1+n,cmp);
s[n+1].l=-1;
for(int i=1;i<=n;i++)
{
int nowpos=lower_bound(myhash+1,myhash+1+2*n,s[i].l)-myhash;
change2(nowpos,1);
}
int ans=1e9;
for(int i=1;i<=n;i++)
{
int nowpos=lower_bound(myhash+1,myhash+1+2*n,s[i].l)-myhash;
change2(nowpos,-1);
int nowposr=lower_bound(myhash+1,myhash+1+2*n,s[i].r)-myhash;
int pre=getsum1(2*n-nowpos+1);
int bac=getsum2(nowposr);
ans=min(ans,n-1-pre-bac);
change1(2*n-nowposr+1,1);
}
cout<< ans<<endl;
}
return 0;
}