个人主页: NiKo
算法专栏:算法设计与分析
目录
题目 2672: 字符统计
- 题目
- 题解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//创建扫描器
Scanner sc = new Scanner(System.in);
//读取字符串
String S = sc.nextLine();
//获取字符串长度
int length = S.length();
//定义一个高级计数器
int[] counts = new int[26];
//关闭扫描器
sc.close();
//通过减去'A'来保证索引为对应的字母编号(非ASCII),从而对每一个字母进行计数
for (int i = 0; i < length; i++) {
counts[S.charAt(i) - 'A']++;
}
//之后找出最大值
int max = 0;
//找出出现次数最多的字母的出现次数
for (int i = 0; i < counts.length; i++) {
//为了不改变原来数组的索引所对应的值
int count = counts[i];
if (count > max) {
max = count;
}
}
//输出出现次数最多的字母的索引,并转化为为字母。
for (int i = 0; i < counts.length; i++) {
if (counts[i] == max) {
System.out.print((char) ('A' + i));
}
}
}
}
题目 2673: 最少刷题数
- 题目
- 题解
import java.util.Arrays;
import java.util.Scanner;
public class ProblemStatistics {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for(int i=0 ; i<n ; i++) {
arr[i]=sc.nextInt();
}
sc.close();
int[] sortarr = arr.clone();
Arrays.sort(sortarr);
int mid = sortarr[n/2];
int more=0 , less=0;
for(int i: arr) {
if(i<mid) less++;
else if(i>mid) more++;
}
int flag=0 , midflag=0;
if(more>=less) flag=1;
if(more>less) midflag=1;
for(int i=0 ; i<n ; i++){ //遍历判断每个数是小于、等于还是大于mid
if(arr[i]<mid){
System.out.print(mid+flag-arr[i]); //flag=1时是case2,3 =0时是case1
}else if(arr[i]==mid && midflag==1){
System.out.print(mid+midflag-arr[i]); //midflag=1时是case2 =0时是case1,3
}else{
System.out.print("0");
}
if(i<n-1) System.out.print(" ");
}
}
}
题目 2674: 求阶乘
- 题目
- 题解
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
long k = scanner.nextLong();
long count;
long a = 5;
while (true) {
long tempA = a;
count = 0;
while (tempA > 0) {
tempA /= 5;
count += tempA;
}
if (count < k) {
a += 5;
} else if (count == k) {
System.out.println(a);
break;
} else {
System.out.println(-1);
break;
}
}
scanner.close();
}
}
题目 2675: 最大子矩阵
- 题目
- 题解
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
typedef pair<int,int>pii;
const int mod = 1e9 + 7 , INF = 0x3f3f3f3f , N = 1e5 + 10;
int g[100][N];
int n,m;
int limit;
struct edge1
{
int v;
int id;
bool operator < (const edge1 & w)const
{
if (v != w.v)
return v < w.v;
return id > w.id;
}
};
struct edge2
{
int v;
int id;
bool operator < (const edge2 & w)const
{
if (v != w.v)
return v > w.v;
return id > w.id;
}
};
struct Node
{
int l,r;
int minv;
int maxv;
}tr[N * 4];
void push_up(int x)
{
tr[x].minv = min(tr[x << 1].minv,tr[x << 1 | 1].minv);
tr[x].maxv = max(tr[x << 1].maxv,tr[x << 1 | 1].maxv);
}
void build(int x,int l,int r)
{
tr[x] = {l,r};
if (l == r)
{
int w = g[(r - 1) % n + 1][(r - 1) / n + 1];
tr[x] = {l,r,w,w};
return;
}
int mid = l + r >> 1;
build(x << 1,l,mid);
build(x << 1 | 1,mid + 1,r);
push_up(x);
}
int queryMin(int x,int l,int r)
{
if (tr[x].l >= l && tr[x].r <= r)
return tr[x].minv;
int mid = tr[x].l + tr[x].r >> 1;
int minv = INF;
if (l <= mid)
minv = queryMin(x << 1,l,r);
if (r > mid)
minv = min(minv,queryMin(x << 1 | 1,l,r));
return minv;
}
int queryMax(int x,int l,int r)
{
if (tr[x].l >= l && tr[x].r <= r)
return tr[x].maxv;
int mid = tr[x].l + tr[x].r >> 1;
int maxv = -1;
if (l <= mid)
maxv = queryMax(x << 1,l,r);
if (r > mid)
maxv = max(maxv,queryMax(x << 1 | 1,l,r));
return maxv;
}
void init()
{
scanf("%d%d",&n,&m);
for (int i = 1 ; i <= n ; i ++)
for (int j = 1 ; j <= m ; j ++)
scanf("%d",&g[i][j]);
scanf("%d",&limit);
build(1,1,n * (m + 1));
}
int getMin(int i1,int j1,int i2,int j2)
{
int a = i1 + n * (j1 - 1);
int b = i2 + n * (j2 - 1);
return queryMin(1,a,b);
}
int getMax(int i1,int j1,int i2,int j2)
{
int a = i1 + n * (j1 - 1);
int b = i2 + n * (j2 - 1);
return queryMax(1,a,b);
}
int main()
{
init();
int res = 0;
for (int i1 = 1 ; i1 <= n ; i1 ++)
for (int i2 = i1 ; i2 <= n ; i2 ++)
{
priority_queue<edge1> q1;
priority_queue<edge2> q2;
for (int l = 1,r = 1; r <= m ; r ++)
{
int maxv = getMax(i1,r,i2,r);
int minv = getMin(i1,r,i2,r);
if (maxv - minv > limit)
{
while (q1.size())
q1.pop();
while (q2.size())
q2.pop();
l = r + 1;
continue;
}
while (q1.size() && q1.top().v <= maxv)
q1.pop();
q1.push({maxv,r});
while (q2.size() && q2.top().v >= minv)
q2.pop();
q2.push({minv,r});
while (q1.top().v - q2.top().v > limit)
{
l ++;
while (q1.size() && q1.top().id < l)
q1.pop();
while (q2.size() && q2.top().id < l)
q2.pop();
}
res = max(res,(i2 - i1 + 1) * (r - l + 1));
}
}
printf("%d",res);
return 0;
}
题目 2676: 数组切分
- 题目
- 题解
// 具有列最大最小值的变形一维数组变形一维求最大子数组(优化:sum预算+跳列遍历)
public static int f3(int lim, int[][] arr) {
int sum = 0;// 变形子数组的最大元素个数(0表示单列不满足)
flag: for (int i = 0; i < arr[0].length; i++) {
int smin = arr[0][i], smax = arr[1][i];
if (smax - smin <= lim) {
sum = Math.max(1, sum);
} else {
continue flag;
}
int sminy = i, smaxy = i;// 记录左极端值的列
for (int j = i + 1; j < arr[0].length; j++) {
// System.out.println(i+" "+j);
if (arr[1][j] > smax) {
if (arr[1][j] - smin > lim) {
i = Math.min(sminy, smaxy);// 跳列遍历
continue flag;
}
smax = arr[1][j];
smaxy = j;
}
if (arr[0][j] < smin) {
if (smax - arr[0][j] > lim) {
i = Math.min(sminy, smaxy);// 跳列遍历
continue flag;
}
smin = arr[0][j];
sminy = j;
}
if (j - i + 1 > sum) {// 此子数组的元素个数
sum = j - i + 1;
}
if (sum >= arr[0].length - i) {// 预算此子数组最大个数,是否还需要遍历
break flag;
}
}
}
return sum;
}
// 十三届省赛第六题,最大子矩阵:二维化一维(枚举行组合)
public static int f4(int lim, int[][] table) {
int sum = 1;
int[][] arr = new int[2][table[0].length];// 具有列最大最小值的变形一维数组
for (int i = 0; i < table.length; i++) {
for (int j = i; j < table.length; j++) {
for (int k = 0; k < arr[0].length; k++) {// 组合为具有列最大最小值的变形一维数组
arr[0][k] = table[i][k];// 初始化
arr[1][k] = table[i][k];// 初始化
for (int t = i; t <= j; t++) {
arr[0][k] = Math.min(table[t][k], arr[0][k]);
arr[1][k] = Math.max(table[t][k], arr[1][k]);
}
}
int mid = f3(lim, arr);
// System.out.println(Arrays.toString(arr[0]));
// System.out.println(Arrays.toString(arr[1]));
// System.out.println(mid);
sum = Math.max(mid * (j - i + 1), sum);
Arrays.fill(arr[0], 0);// 清除
Arrays.fill(arr[1], 0);// 清除
}
}
return sum;
}
题目 2677: 回忆迷宫
- 题目
- 题解
// 十三届省赛第八题,回忆迷宫:先填墙(路边+内空)再挖路
static Character[][] table = new Character[300][300];// 取150,150为中心开始
public static void f7(char[] arr) {
int nx = 150, ny = 150, mx = 150, my = 150;// 最小最大的坐标,输出用
for (Character[] cs : table) {
Arrays.fill(cs, ' ');// 初始化
}
int[][] empty = new int[2][arr.length + 1];
int x = 150, y = 150;// 初始化位坐标
empty[0][0] = 150;// 初始化路的x坐标
empty[1][0] = 150;// 初始化路的y坐标
// 填墙
table[x - 1][y] = '*';// 初始化坐标墙
table[x + 1][y] = '*';// 初始化坐标墙
table[x][y - 1] = '*';// 初始化坐标墙
table[x][y + 1] = '*';// 初始化坐标墙
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 'U') {// 上
x--;
} else if (arr[i] == 'D') {// 下
x++;
} else if (arr[i] == 'R') {// 右
y++;
} else if (arr[i] == 'L') {// 左
y--;
}
empty[0][i + 1] = x;// 记录路的x坐标
empty[1][i + 1] = y;// 记录路的y坐标
nx = Math.min(nx, x);// 维持最小x坐标
ny = Math.min(ny, y);// 维持最小y坐标
mx = Math.max(mx, x);// 维持最大x坐标
my = Math.max(my, y);// 维持最大y坐标
table[x - 1][y] = '*';// 填墙
table[x + 1][y] = '*';// 填墙
table[x][y - 1] = '*';// 填墙
table[x][y + 1] = '*';// 填墙
}
// for (int i = nx - 1; i <= mx + 1; i++) {
// for (int j = ny - 1; j <= my + 1; j++) {
// System.out.print(table[i][j]);
// }
// System.out.println();
// }
// System.out.println("==================");
// 填满中间(dfs深搜法,全面)
f8(nx-1,ny-1,mx+1,my+1);
// for (int i = nx - 1; i <= mx + 1; i++) {
// for (int j = ny - 1; j <= my + 1; j++) {
// System.out.print(table[i][j]);
// }
// System.out.println();
// }
// System.out.println("==================");
// 挖空
for (int i = 0; i < empty[0].length; i++) {
table[empty[0][i]][empty[1][i]] = ' ';
}
for (int i = nx - 1; i <= mx + 1; i++) {
for (int j = ny - 1; j <= my + 1; j++) {
System.out.print(table[i][j]);
}
System.out.println();
}
}
//填满中间,dfs深搜
static Character[][] copy=new Character[table.length][];
public static void f8(int nx,int ny,int mx,int my) {//左上右下坐标
for (int i = 0; i < copy.length; i++) {
copy[i]=table[i].clone();//复制表格
}
for (int i = nx; i <= mx; i++) {
for (int j = ny; j <= my; j++) {
if (copy[i][j] == ' ') {// 如果是一个被包围的空格则填墙
dfs(nx, ny, mx, my, i, j);
//填充原表格
if(flag) {
for (int k = 0; k < listx.size(); k++) {
table[listx.get(k)][listy.get(k)]='*';
}
}
//恢复
flag=true;
listx.clear();
listy.clear();
}
}
}
}
static boolean flag=true;
static List<Integer> listx=new ArrayList<Integer>();
static List<Integer> listy=new ArrayList<Integer>();
public static void dfs(int nx,int ny,int mx,int my,int x,int y) {//左上右下坐标
copy[x][y]='*';
listx.add(x);
listy.add(y);
if(x==nx||x==mx||y==ny||y==my) {
flag=false;
}
if(copy[x][y+1]==' '&&y+1<=my) {
dfs(nx, ny, mx, my, x, y+1);
}
if(copy[x][y-1]==' '&&y-1>=ny) {
dfs(nx, ny, mx, my, x, y-1);
}
if(copy[x+1][y]==' '&&x+1<=mx) {
dfs(nx, ny, mx, my, x+1, y);
}
if(copy[x-1][y]==' '&&x-1>=nx) {
dfs(nx, ny, mx, my, x-1, y);
}
}
题目 2678: 红绿灯
- 题目
题目 2679:拉箱子
- 题目