题目描述
Farmer John 的奶牛们的早餐最爱当然是麦片了!事实上,奶牛们的胃口是如此之大,每头奶牛一顿饭可以吃掉整整一箱麦片。
最近农场收到了一份快递,内有 M 种不同种类的麦片(1≤M≤10^5)。不幸的是,每种麦片只有一箱!N 头奶牛(1≤N≤10^5)中的每头都有她最爱的麦片和第二喜爱的麦片。给定一些可选的麦片,奶牛会执行如下的过程:
- 如果她最爱的麦片还在,取走并离开。
- 否则,如果她第二喜爱的麦片还在,取走并离开。
- 否则,她会失望地哞叫一声然后不带走一片麦片地离开。
奶牛们排队领取麦片。对于每一个 0≤i≤N−1,求如果 Farmer John 从队伍中移除前 i 头奶牛,有多少奶牛会取走一箱麦片。
输入格式
输入的第一行包含两个空格分隔的整数 N 和 M。
对于每一个1≤i≤N,第 i 行包含两个空格分隔的整数 fi 和 si(1≤fi,si≤M,且 fi != si),为队伍中第 i 头奶牛最喜爱和第二喜爱的麦片。
输出格式
对于每一个0≤i≤N−1,输出一行,包含对于 i 的答案。
输入输出样例
输入 #1
4 2 1 2 1 2 1 2 1 2
输出 #1
2 2 2 1
说明/提示
样例解释
如果至少两头奶牛留下,那么恰有两头奶牛取走了一箱麦片。
子任务
- 测试点 2-3 满足 N,M≤10^3。
- 测试点 4-10 没有额外限制。
解题代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static final int N = 100010;
static int n;
static int m;
static int[][] fond = new int[N][2];//记录她们喜欢的麦片
static int[] a = new int[N];//记录麦片被那一头牛拿走了
static int count;
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
for(int i = 1; i <= n; i++){
fond[i][0] = scanner.nextInt();
fond[i][1] = scanner.nextInt();
}
int[] b = new int[N];
Arrays.fill(a,0);//初始化都没有被拿走
for (int i = n; i >= 1; i--) {
solve(i ,fond[i][0]);
b[i] = count;
}
for(int i = 1; i <= n; i++) System.out.println(b[i]);
}
public static void solve(int x,int y){//x表示当前选择麦片的牛,y表示当前牛选择的麦片
if(a[y] == 0){//最喜欢的没有被拿走
a[y] = x;
count++;
} else if (a[y] > x) {
int z = a[y];//记录之前选择该麦片的扭扭
a[y] = x;//重新为当前扭扭选择该麦片
if(y == fond[z][0]) solve(z,fond[z][1]);//被抢走麦片的扭扭就要重新选择
//被选择的麦片数没有变,不需要加一
}
}
}
解题思路
如果按照常规方法,从0到n-1进行枚举,模拟奶牛选择麦片的过程,很容易就时间超限了。所以需要改变一下思路,从后往前进行遍历每一头奶牛选择麦片,然后再将结果倒着输出就可以了。
- 因为是从后往前,所以前面的优先级会大于后面,故在选择时会出现两种情况
- 如果最喜欢的麦片没有被选择,直接选择该麦片即可
- 如果最喜欢的麦片已经被选择了,由于当前奶牛的优先级比后面的大,所以可以抢过来。而且要对后面奶牛进行判断,如果这是它第一喜欢的麦片,可以帮他递归求第二喜欢的麦片的选择;否则就是它没有麦片了。
感觉这个很适合用栈写,太弱啦不会(好吧就是懒)。。。。