C. Grouping Increases

文章探讨了一种解决两个序列添加元素时保持顺序并考虑代价的问题,通过将序列比喻为具有容积限制的箱子,利用贪心决策来决定在哪个箱子中放置元素,以最小化总代价。

Here

解题思路

  • 两个序列,保持顺序
  • 对于代价的产生进行考虑
  • 当添入一个大于当前序列最后值的数,代价加1,但下次判断标准变大
  • 当添入一个小于当前序列最后值的数,代价不增,但下次判断标准变小
  • 考虑形象化描述
  • 将两个序列看作两个箱子,箱子有容积的限制
  • 只能放入比它小的箱子,且下一次只能在新放入的箱子内再放
  • 即只允许箱子套箱子,不允许箱子叠放
  • 所以添入一个小于当前序列最后值的数,看作大箱子内放小箱子,容积变小
  • 考虑贪心决策
  • 对于两个箱子,进行比较,定义b为容积较大的,c较小
  • 则能往c中放的,放c中,减少容积损失
  • 不能放c能往b中放的,放b
  • 均不能放的,则将较小的箱子c删去,换为当前a_i大小的箱子,代价加1,减少容积损失

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)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	static int N=2000010;
	static int n=0;
	static int m=0;
	
	
	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();
			int[] a=new int[n+1];
			for(int i=1;i<=n;++i)a[i]=input.nextInt();
			int num=0;
			int b=inf;
			int c=inf;
			for(int i=1;i<=n;++i) {
				
				if(a[i]<=c) {
					c=a[i];
				}else if(a[i]<=b) {
					b=a[i];
				}else {
					num++;
					c=a[i];
				}
				if(c>b) {
					int t=c;
					c=b;
					b=t;
				}
			}
			out.println(num);
 		}
		
	    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();
		    }
		}
	}

		

	

 

<think> 我们被要求提供Collectors.groupingBy进行多重分组的语法。根据引用[2]中的信息,groupingBy收集器可以用于分组,并且支持多级分组(即多重分组)。多重分组可以通过连续使用groupingBy方法实现,即在外层groupingBy的下游收集器中再嵌套另一个groupingBy。 具体语法如下: 假设我们有一个流,要按两个属性进行分组:首先按属性A分组,然后在每个A组内再按属性B分组,那么我们可以这样写: Map<A, Map<B, List<元素类型>>> result = list.stream() .collect(Collectors.groupingBy(元素::getA, Collectors.groupingBy(元素::getB))); 注意: 1. 第一个groupingBy的参数是第一个分类函数(例如:元素::getA),第二个参数是下游收集器。 2. 在下游收集器中,我们再次使用groupingBy,按第二个分类函数(例如:元素::getB)进行分组。 3. 这样我们就得到了一个两级Map结构。 另外,我们也可以在下游收集器中指定其他收集器,比如如果我们不想得到List,而是想对分组后的元素进行某种聚合操作,可以使用其他收集器,如counting()、summingInt()等。 例如,如果我们想按A分组,然后再按B分组,并统计每个B组内的元素个数,可以这样写: Map<A, Map<B, Long>> result = list.stream() .collect(Collectors.groupingBy(元素::getA, Collectors.groupingBy(元素::getB, Collectors.counting()))); 所以,多重分组的关键是在下游收集器中再次使用groupingBy。 根据引用[1]中的说明,groupingBy收集器使用另一个下游收集器作为组,这样就不需要将组收集到列表中再进行处理,而是直接在下游收集器中指定操作。 因此,回答中应给出基本的多重分组语法示例,并说明其结构。 </think>### Collectors.groupingBy多重分组的语法 在Java Stream API中,使用`Collectors.groupingBy`进行多重分组时,可通过嵌套分组操作实现多级分类。核心语法结构如下: ```java Map<一级分组键, Map<二级分组键, 结果类型>> result = collection.stream() .collect(Collectors.groupingBy( 一级分组函数, Collectors.groupingBy( 二级分组函数, 下游收集器 ) )); ``` #### 关键组成部分: 1. **一级分组函数** 使用`Function`提取第一级分组键,如:`元素::getPropertyA` 2. **嵌套groupingBy** 作为下游收集器,传入二级分组函数:`Collectors.groupingBy(元素::getPropertyB)` 3. **下游收集器(可选)** 最内层可指定聚合操作(默认为`toList()`),如: - `Collectors.counting()` 统计数量 - `Collectors.summingInt()` 求和 - `Collectors.toSet()` 转Set集合 #### 示例代码: ```java // 按部门分组,再按职位分组统计薪资总和 Map<String, Map<String, Integer>> result = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.groupingBy( Employee::getPosition, Collectors.summingInt(Employee::getSalary) ) )); ``` #### 输出结构: ```json { "技术部": { "工程师": 150000, "架构师": 200000 }, "市场部": { "经理": 120000 } } ``` #### 特性说明: 1. **支持无限嵌套** 可通过连续嵌套实现三级及以上分组 2. **灵活聚合** 每层可独立指定聚合操作(引用[2]) 3. **避免中间集合** 直接聚合无需暂存中间列表(引用[1]) 4. **线程安全** 适用于并行流处理 > 注:分组键可为`null`,此时会创建单独的`null`键分组。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值