Div2 904 C. Medium Design

文章描述了一种方法,利用树状数组和离散化技术处理区间问题,通过维护区间端点并结合优先队列,高效地找到满足特定条件的最大区间数量。
摘要由CSDN通过智能技术生成

Here 

 

解题思路 

  • 对于所给的区间可以任意选择
  • 若该点为最大值,则包含他的区间都要,其余区间不要,为最大值的点一定为区间端点
  • 有区间加,考虑树状数组维护
  • 区间端点为1e9,放不下,但因为端点是离散的,最多有n个不同,考虑离散化映射到1\rightarrow n
  • 将区间按左端点由小到大进行排序,得到数组a
  • 然后从小到大枚举映射后的端点,设此时端点i为最大值的选取点
  • 对于左端点小于i的区间,进行树状数组区间加(在a上进行二分,找j\geq i,min\ j,或者用优先队列)
  • 并将使用的区间加入优先队列us(按区间右端点由小到大进行排序)
  • 将队列中右端点小于i的弹出,并用区间减消除影响
  • 此时的最小值一定在离散后的最大最小端点和所有区间不包含的点(特判)

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();
		    }
		}
	}

		

	

 

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值