- 世界杯开幕式会在球场C举行,球场C的球迷看台可以容纳M*N个球迷。在球场售票完成后,现官方想统计此次开幕式一共有多少个球队球迷群体,最大的球队球迷群体有多少人。
经调研发现,球迷群体在选座时有以下特性:
同球队的球迷群体会选择相邻座位,不同球队的球迷群体会选择不相邻的座位(注解:相邻包括前后相邻,左右相邻,斜对角相邻)
给定一个M*N的二维球场,0代表该位置没有坐人,1代表该位置已有选择,希望输出球队群体个数P,最大的球队群体人数Q
输入描述:
第一行,2个数字,M及N,使用英文逗号分隔
接下来M行,每行N的数字,使用英文逗号分隔
输出描述:
一行,2个数字,P及Q,使用英文逗号分隔
其中P表示球队群体个数,Q表示最大的球队群体人数
例:输入
10,10
0,0,0,0,0,0,0,0,0,0
0,0,0,1,1,0,1,0,0,0
0,1,0,0,0,0,0,1,0,1
1,0,0,0,0,0,0,0,1,1
0,0,0,1,1,1,0,0,0,1
0,0,0,0,0,0,1,0,1,1
0,1,1,0,0,0,0,0,0,0
0,0,0,1,0,1,0,0,0,0
0,0,1,0,0,1,0,0,0,0
0,1,0,0,0,0,0,0,0,0
输出:6,8
import java.util.Scanner;
public class BallFan {
public static int m = 0;
public static int n = 0;
public static int total = 0;
public static void main (String[] args){
Scanner sc = new Scanner(System.in);
String[] m_n = sc.nextLine().split(",");
m = Integer.parseInt(m_n[0]);//行
n = Integer.parseInt(m_n[1]);//列
if (m <= 0 || n <= 0) return;
int[] arr = new int[n*m + 1];//用一维数组存储
int i = 1;
for(int j=0; j < m; j++){
String[] line = sc.nextLine().split(",");
for (int k=0; k < n; k++){
arr[i] = Integer.parseInt(line[k]);
i++;
}
}
int groups = 0;//组数
int max = 0;//最大人数
for (int j=1; j <= n*m; j++){
if (arr[j] == 0) continue;
groups++;
total = 0;
//递归求解
countMumber(arr, j);
if (total > max)
max = total;
}
System.out.println(groups + "," + max);
}
public static void countMumber (int[]arr, int poi){
if (arr[poi] == 0) return;
arr[poi] = 0;
total++;
//确定当前游标位置,根据游标位置取方位值
if (poi % n != 0){//最右并不需要向右边寻值,我们可以认为是一个从左到右的过程
countMumber(arr, poi+1);
}
if (poi % n != 1){//最左并不需要向左边寻值
countMumber(arr, poi-1);
}
if (n*m - n > poi){//不位于下边界即可向下探索
int down = poi + n;
countMumber(arr, down);//向下寻值
if (down % n != 0){//非最右
countMumber(arr, down+1);//下右对角线
}
if (down % n != 1){//非最左
countMumber(arr, down-1);//下左对角线
}
}
if (n < poi){
int up = poi - n;
countMumber(arr, up);//向上寻值
if (up % n != 0){//非最右
countMumber(arr, up+1);//上右对角线
}
if (up % n != 1){//非最左
countMumber(arr, up-1);//上左对角线
}
}
}
}
- 为了提高文章质量,每一篇文章(假设全部都是英文)都会有m名编辑进行审核,每个编辑独立工作,会把觉得有问题的句子通过下表记录下来,比如[1,10],1表示病句的第一个字符,10表示病句的最后一个字符。也就是从1到10着10个字符组成的句子,是有问题的。
现在需要把多名编辑有问题的句子合并起来,送个总编辑进行最终的审核。比如编辑A指出的病句是[1,10],[32,45];编辑B指出的病句是[5,16],[78,94]那么[1,10]和[5,16]是有交叉的,可以合并成[1,16][32,45][78,94]
输入描述:
编辑数量m,之后每行是每个编辑的标记的下表组合,第一个和最后一个下标用英文逗号分隔,每组下标之间用分号分隔
输出描述:
合并后的下标集合,第一个和最后一个下标用英文逗号分隔,每组下标之间用分号分隔。返回结果是从小到大递增排列
例:输入
3
1,10;32,45
78,94;5,16
80,100;200,220;16,32
输出: 1,45;78,100;200,220
package test2;
import java.util.*;
public class ErrTopic {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int lines = Integer.parseInt(sc.nextLine());
HashMap <Integer,Integer> hs = new HashMap<>();
int groups = 1;
for (int i=0; i < lines; i++){
String[] finds = sc.nextLine().split(";");
for (String area: finds){
String[] deatil = area.split(",");
int begin = Integer.parseInt(deatil[0]);
int end = Integer.parseInt(deatil[1]);
hs.put(begin, end);
groups++;
}
}
int[] arr = new int[(groups-1)*2];
int k = 0;
for (Integer i: hs.keySet()){
arr[k] = i;
arr[k+1] = hs.get(i);
k += 2;
}
Arrays.sort(arr);//升序排列
int begin = arr[0];//启动组编号
int end = hs.get(begin);//截至组编号
int current;//当前位置
String result = "";
for (int i=1; i < arr.length; i++){
current = arr[i];
if (hs.get(current) != null){//证明current是一个起始位
int comp = hs.get(current);
end = comp > end ?comp: end;
continue;
}else if(current == end){
if (result != ""){
result += ";";
}
result += begin + "," + end;
if (i+1 < arr.length) {
begin = arr[i + 1];
end = hs.get(begin);
}
}
}
System.out.println(result);
}
}
- 小a和小b玩一个游戏,有n张卡牌,每张上面有两个正整数x,y。取一张牌时,个人积分增加x,团队积分增加y。求小a,小b各取若干张牌,使得他们的个人积分相等,且团队积分最大。
用例描述:
输入:
4 # n=4 组数据
3 1 # x, y
2 2
1 4
1 4
输出:10
import java.util.Scanner;
public class MaxTearmCard {
public static void main (String[] args){
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
int[] person_score = new int[count+1];//记录一张卡片的个人分数
int[] team_score = new int[count+1];//记录一张卡片的团队分数
int max = 0;
for (int i=1; i <= count; i++){
person_score[i] = sc.nextInt();
team_score[i] = sc.nextInt();
max = max > person_score[i] ? max : person_score[i];
}
//i行第j列表示,从第1张牌到第n张牌的最大团队收益
//这里之所以使用max是a抽到的牌比b的最大值
//也可以不使用max而改用person_score所有值的和,但没必要
int[][] teamMax = new int[count+1][max+1];
getTeamMax(teamMax, max, person_score, team_score);
// for (int i=0; i < count+1; i++){
// for (int j=0; j < max+1; j++)
// System.out.print(teamMax[i][j] + " ");
// System.out.println();
// }
System.out.println(teamMax[count][0]);
sc.close();
}
public static void getTeamMax (int[][] teamMax, int max,
int[] pesron_score, int[] team_score) {
//只需要考虑a比b的情况,二者是对称的
for (int i=1; i < teamMax.length; i++){//外层控制a-b的差值
for (int j=0; j <= max; j++){//内层控制选择到第i张牌
if (i == 1 && j == 0)
continue;//只有一张牌差值为0的情况不存在,跳过
int aGetMax = 0;//a获取第i张牌后当前团队最大积分
int aLostMax = 0;//b获取第i张牌后当前团队最大积分
//假设a在接受第i张牌前,只比b大j-pesron_score[i]
//即把第i张牌分配给a的情况
if (j - pesron_score[i] >= 0){
aGetMax = teamMax[i-1][j-pesron_score[i]]
+ team_score[i];
}
//把第i张牌给b的情况,即a-b差值从j+person_score[i]减到j
if(j + pesron_score[i] <= max){
aLostMax = teamMax[i-1][j+pesron_score[i]]
+ team_score[i];
}
//teamMax[i-1][j]代表谁也不分配牌的情况
teamMax[i][j] = Math.max(Math.max(aGetMax, aLostMax), teamMax[i-1][j]);
}
}
}
}
-
两个长度为n的序列a,b。问a中有多少个区间[l,r]满足max(a[l,r])<min(b[l,r])
即a区间的最大值小于b区间的最小值数据范围:n<1e5,a(i),b(i)<1e9
输入描述:
第一行一个整数n
第二行n个数,第i个为a(i)
第三行n个数,第i个为b(i)
0<1<=r<n
输出描述:
一行一个整数,表示答案
例1:输入
3
3 2 1
3 3 3
输出: 3import java.util.*; public class CompAbArea { //思路: //1. 对a组合使用map进行虑重 //2. 对b使用set进行虑重 //3. 将a虑重结果放入list中 //4. 比较ab public static void main (String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt();//a和b的元素个数都为n int[] a = new int[n]; HashSet<Long> bSet = new HashSet<>(); for (int i=0; i < n; i++) a[i] = sc.nextInt(); for (int i=0; i < n; i++) bSet.add(sc.nextLong()); HashMap<String, Long> hs = new HashMap<>(); for(int i=0; i < n; i++){//外层控制增量 int lf = 0;//左边界 int rt = lf + i;//右边界 while (rt < n){ long max = a[lf]; String str = ""; for(int k=lf; k <= rt; k++) { max = max > a[k] ? max : a[k]; if(str != "") str += ","; str += a[k]; } lf = lf+1; rt = lf+i; hs.put(str, max);//采用map过滤重复顺序 } } List<Long> maxLs = new ArrayList<>(); for(long v : hs.values()){ maxLs.add(v); } int result = 0; for (int i=0; i < maxLs.size(); i++){ Iterator<Long> ite = bSet.iterator(); while(ite.hasNext()){ if(ite.next() > maxLs.get(i)){ result++; break; } } } System.out.println(result); } }
-
小明在抖音里关注了N个主播,每个主播每天的开播时间是固定的,分别在S时刻开始开播,t时间结束。小明无法同时观看两个主播的直播。一天被分成了M个时间单位。请问小明每天最多能完整观看多少场直播?
输入描述:
第一行一个整数,代表N
第二行一个整数,代表M
第三行空格间隔的N*2个整数,代表s,t
输出描述:
一行一个整数,表示答案
例1:输入
3
10
0 3 3 7 7 0
输出:3
例2: 输入
3
10
0 5 2 7 6 9
输出:2
备注:数据范围1<=N<=10^5
2<=M<=10^6
0<=s(i),t(i)<M (s(i)!=t(i))
s(i)>t(i)代表时间跨天,但直播时长不会超过一天import java.util.*; public class MaxLive { //思路:从某一区间出发,向右吞并 public static void main (String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); List<Live> ls = new ArrayList<>(n); for (int i=0; i < n; i++){ int start = sc.nextInt(); int end = sc.nextInt(); ls.add(new Live(start, end)); } //先排序链表 Collections.sort(ls, new LiveComparator()); //开始执行吞并 int max = 0; for (int i=0; i < n; i++){ int lf = ls.get(i).start; int rt = ls.get(i).end; int total = 1; for(int j=(i+1)%n; j!=i; j=(j+1)%n){ int cs = ls.get(j).start; int ce = ls.get(j).end; if (rt <= cs && cs <= ce || rt <= cs && ce <= lf || ce <= cs && cs <= lf) { rt = ce; total++; } } max = max > total ? max : total; } System.out.println(max); } public static class Live{ int start; int end; public Live(int start, int end) { this.start = start; this.end = end; } @Override public String toString() { return "Live{" + "start=" + start + ", end=" + end + '}'; } } public static class LiveComparator implements Comparator<Object>{ @Override public int compare(Object o1, Object o2) { Live l1 = (Live)o1; Live l2 = (Live)o2; int c1 = l1.start - l2.start; if (c1 == 0){ if(l1.start > l1.end && l1.start > l2.end)//出现两个跨天 return -(l1.end - l2.end); if(l1.start > l1.end && l1.start <= l2.end){//单个跨天 return 1; } if(l1.start > l2.end && l1.start <= l1.end){//单个跨天 return -1; } return l1.end - l2.end; } return c1; } } }
-
抖音工程师想要找到抖音里的红人。
假设用户数为N,有M个关注关系对(A,B)。
(A,B)表示用户A关注了用户B,关注关系具有传递性,
例如:用户A关注了用户B,用户B关注了用户C,那么A间接关注了C.
如果一个用户被N个用户直接或间接关注,
那么我们认为这个用户是抖音红人。求抖音红人的总数
输入描述:
第一行一个整数,代表N
第二行一个整数,代表M
第三行空格分隔的M*2个整数,代表关注关系对
输出描述:
一行一个整数,表示答案
如:
输入
3
3
1 2 2 1 2 3
1import java.util.*; public class HotMan { //注意:这题有一个坑,即默认自己关注自己,因此要算的是关注人数 >= N-1即可 public static void main (String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt();//关注个数 int m = sc.nextInt();//关系对数 HashMap<Integer, HashSet<Integer>> hs = new HashMap<>(n); for (int i=0; i < m; i++){ int a = sc.nextInt();//关注者 int b = sc.nextInt();//被关注者 HashSet<Integer> set = new HashSet<>();//关注者名单 if (hs.get(b) != null) { set = hs.get(b); } set.add(a); hs.put(b, set); } int count = 0; for(Integer b : hs.keySet()) { HashMap<Integer, Integer> total = new HashMap<>(); findRelation(hs, total, b); if (total.size()>= n) count++; } System.out.println(count); } public static void findRelation (HashMap<Integer,HashSet<Integer>> hs, HashMap<Integer, Integer> total, int num){ if (total.get(num) != null) return; total.put(num, 1); HashSet<Integer> set = hs.get(num); Iterator<Integer> ite = set.iterator(); while(ite.hasNext()){ int i = ite.next(); if (total.get(i) != null) continue; findRelation(hs, total, i); } } }