解题思路
- 对于所给的区间可以任意选择
- 若该点为最大值,则包含他的区间都要,其余区间不要,为最大值的点一定为区间端点
- 有区间加,考虑树状数组维护
- 区间端点为1e9,放不下,但因为端点是离散的,最多有n个不同,考虑离散化映射到
- 将区间按左端点由小到大进行排序,得到数组
- 然后从小到大枚举映射后的端点,设此时端点
为最大值的选取点
- 对于左端点小于
的区间,进行树状数组区间加(在
上进行二分,找
,或者用优先队列)
- 并将使用的区间加入优先队列
(按区间右端点由小到大进行排序)
- 将队列中右端点小于
的弹出,并用区间减消除影响
- 此时的最小值一定在离散后的最大最小端点和所有区间不包含的点(特判)
import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
//implements Runnable
public class Main {
static long md=(long)1e9+7;
static long Linf=Long.MAX_VALUE/2;
static int inf=Integer.MAX_VALUE/2;
static int N=2000100;
static int n=0;
static int m=0;
static
class Node{
long x;
long y;
public Node() {
}
public Node(long u,long v) {
x=u;
y=v;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node now = (Node) o;
return x==now.x&&y==now.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
static
class BIT{
int size;
int[] tr;
public BIT(int N) {
size=N;
tr=new int[N+1];
}
int lowbit(int x) {
return x&(-x);
}
void update(int x,int k) {
for(int i=x;i<=size;i+=lowbit(i)) {
tr[i]+=k;
}
}
int qurty(int x) {
int res=0;
for(int i=x;i>0;i-=lowbit(i)) {
res+=tr[i];
}
return res;
}
}
static void solve() throws Exception{
AReader input=new AReader();
// Scanner input=new Scanner(System.in);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
String al="abcdefghijklmnopqrstuvwxyz";
char[] ac=al.toCharArray();
int T=input.nextInt();
while(T>0) {
T--;
n=input.nextInt();
m=input.nextInt();
Node[] a=new Node[n+1];
boolean ok=false;
int mx=0;
int mi=inf;
TreeSet<Long> q=new TreeSet<Long>();
for(int i=1;i<=n;++i) {
long l=input.nextLong();
long r=input.nextLong();
a[i]=new Node(l,r);
q.add(l);
q.add(r);
mi=Math.min(mi, (int)l);
mx=Math.max(mx, (int)r);
}
if(mi!=1||mx!=m)ok=true;
HashMap<Long, Integer> hs=new HashMap<Long, Integer>();
int t=0;
for(long x:q) {
t++;
hs.put(x, t);
}
Arrays.sort(a,1,n+1,(o1,o2)->{
if(o1.x-o2.x>0)return 1;
else if(o1.x-o2.x<0)return -1;
else {
if(o1.y-o2.y>0)return 1;
else if(o1.y-o2.y<0)return -1;
else return 0;
}
});
BIT rel=new BIT(t+10);
int o=1;
mx=0;
PriorityQueue<Node> us=new PriorityQueue<Node>((o1,o2)->{
if(o1.y-o2.y>0)return 1;
else if(o1.y-o2.y<0)return -1;
else return 0;
});
for(int i=1;i<=t;++i) {
while(!us.isEmpty()) {
Node op=us.peek();
int l=hs.get(op.x);
int r=hs.get(op.y);
if(r>=i)break;
us.poll();
rel.update(l, -1);
rel.update(r+1, 1);
}
int l=o,r=n;
int id=-1;
while(l<=r) {
int mid=(l+r)>>1;
if(hs.get(a[mid].x)<=i)l=mid+1;
else {
r=mid-1;
id=mid;
}
}
if(id==-1) {
for(int j=o;j<=n;++j) {
rel.update(hs.get(a[j].x), 1);
rel.update(hs.get(a[j].y)+1, -1);
us.add(new Node(a[j].x,a[j].y));
}
o=n+1;
}else {
for(int j=o;j<id;++j) {
rel.update(hs.get(a[j].x), 1);
rel.update(hs.get(a[j].y)+1, -1);
us.add(new Node(a[j].x,a[j].y));
}
o=id;
}
int now=rel.qurty(i);
mi=Math.min(rel.qurty(1), rel.qurty(t));
if(ok)mx=Math.max(mx, now);
else mx=Math.max(mx, now-mi);
}
out.println(mx);
}
out.flush();
out.close();
}
public static void main(String[] args) throws Exception{
solve();
}
// public static final void main(String[] args) throws Exception {
// new Thread(null, new Tx2(), "线程名字", 1 << 27).start();
// }
// @Override
// public void run() {
// try {
// //原本main函数的内容
// solve();
//
// } catch (Exception e) {
// }
// }
static
class AReader{
BufferedReader bf;
StringTokenizer st;
BufferedWriter bw;
public AReader(){
bf=new BufferedReader(new InputStreamReader(System.in));
st=new StringTokenizer("");
bw=new BufferedWriter(new OutputStreamWriter(System.out));
}
public String nextLine() throws IOException{
return bf.readLine();
}
public String next() throws IOException{
while(!st.hasMoreTokens()){
st=new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
public char nextChar() throws IOException{
//确定下一个token只有一个字符的时候再用
return next().charAt(0);
}
public int nextInt() throws IOException{
return Integer.parseInt(next());
}
public long nextLong() throws IOException{
return Long.parseLong(next());
}
public double nextDouble() throws IOException{
return Double.parseDouble(next());
}
public float nextFloat() throws IOException{
return Float.parseFloat(next());
}
public byte nextByte() throws IOException{
return Byte.parseByte(next());
}
public short nextShort() throws IOException{
return Short.parseShort(next());
}
public BigInteger nextBigInteger() throws IOException{
return new BigInteger(next());
}
public void println() throws IOException {
bw.newLine();
}
public void println(int[] arr) throws IOException{
for (int value : arr) {
bw.write(value + " ");
}
println();
}
public void println(int l, int r, int[] arr) throws IOException{
for (int i = l; i <= r; i ++) {
bw.write(arr[i] + " ");
}
println();
}
public void println(int a) throws IOException{
bw.write(String.valueOf(a));
bw.newLine();
}
public void print(int a) throws IOException{
bw.write(String.valueOf(a));
}
public void println(String a) throws IOException{
bw.write(a);
bw.newLine();
}
public void print(String a) throws IOException{
bw.write(a);
}
public void println(long a) throws IOException{
bw.write(String.valueOf(a));
bw.newLine();
}
public void print(long a) throws IOException{
bw.write(String.valueOf(a));
}
public void println(double a) throws IOException{
bw.write(String.valueOf(a));
bw.newLine();
}
public void print(double a) throws IOException{
bw.write(String.valueOf(a));
}
public void print(char a) throws IOException{
bw.write(String.valueOf(a));
}
public void println(char a) throws IOException{
bw.write(String.valueOf(a));
bw.newLine();
}
}
}