双指针


所有类似这样的算法都是双指针算法,时间复杂度为O(n)

AcWing 1238. 日志统计

小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。

其中每一行的格式是:

ts id
表示在 ts 时刻编号 id 的帖子收到一个”赞”。

现在小明想统计有哪些帖子曾经是”热帖”。

如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。

具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。

给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。

输入格式
第一行包含三个整数 N,D,K。

以下 N 行每行一条日志,包含两个整数 ts 和 id。

输出格式
按从小到大的顺序输出热帖 id。

每个 id 占一行。

数据范围
1≤K≤N≤105,
0≤ts,id≤105,
1≤D≤10000
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3

思路

考试的时候多想几种循环方式,选一个可以优化的
一、暴力枚举
1、先循环id,再循环时间段
2、先循环时间段,在循环id

然后写一下伪代码,分析一下如何优化,在这里我们就考虑一下把内循环for(id)进行优化
我们从实际来分析:

因为时间段是根据[T, T + D]来确定的,也就是每一个时间点都有一个时间段,但可以看到,时间段有大部分是重复的,只有开头结尾不一样,中间都是重复的,

那我们如何不重复的遍历时间段呢?
我们只需要在遍历下一个时间段时,利用上一个时间段减去头部,再加上尾部变成下一个时间段,避免重复工作。
优化后

所以我们需要同时循环i,j下标,也就是双指针

代码

import java.io.*;
import java.util.*;public class Main {static final int N = 100010;static int n, d, k;static int[] cnt = new int[N];static boolean[] st = new boolean[N];static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static PIIs[] logs = new PIIs[N];static int Int(String s) {return Integer.parseInt(s);}public static void main(String[] args) throws IOException {String[] s = in.readLine().split(" ");n = Int(s[0]);d = Int(s[1]);k = Int(s[2]);for (int i = 0; i < n; i ++ ){s = in.readLine().split(" ");logs[i] = new PIIs(Int(s[0]),Int(s[1]));}Arrays.sort(logs, 0, n);for (int i = 0, j = 0; i < n; i ++ ) {int id = logs[i].id;cnt[id] ++ ;while (logs[i].t - logs[j].t >= d) {cnt[logs[j].id] -- ;j ++ ;}if (cnt[id] >= k) st[id] = true;}for (int i = 0; i <= 100000; i ++ ) {if (st[i]) System.out.println(i);}}}class PIIs implements Comparable<PIIs> {int t;int id;public PIIs(int t, int id) {this.t = t;this.id = id;}public int compareTo(PIIs o) {return Integer.compare(this.t, o.t);}
}

AcWing 1101. 献给阿尔吉侬的花束(背一下)

阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。

今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。

现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。

迷宫用一个 R×C 的字符矩阵来表示。

字符 S 表示阿尔吉侬所在的位置,字符 E 表示奶酪所在的位置,字符 # 表示墙壁,字符 . 表示可以通行。

阿尔吉侬在 1 个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。

输入格式
第一行是一个正整数 T,表示一共有 T 组数据。

每一组数据的第一行包含了两个用空格分开的正整数 R 和 C,表示地图是一个 R×C 的矩阵。

接下来的 R 行描述了地图的具体内容,每一行包含了 C 个字符。字符含义如题目描述中所述。保证有且仅有一个 S 和 E。

输出格式
对于每一组数据,输出阿尔吉侬吃到奶酪的最少单位时间。

若阿尔吉侬无法吃到奶酪,则输出“oop!”(只输出引号里面的内容,不输出引号)。

每组数据的输出结果占一行。

数据范围
1<T≤10,
2≤R,C≤200
输入样例:
3
3 4
.S…
###.
…E.
3 4
.S…
.E…

3 4
.S…

…E.
输出样例:
5
1
oop!

思路


一层层往下扩展,第一次搜到终点时就是最小路径

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;public class Main {static final int N = 210;static int n;static int m;static char[][] g = new char[N][N];static int[][] dist = new int[N][N];static PIIs start;static PIIs end;static int[] dx = {-1, 0, 1, 0};static int[] dy = {0, 1, 0, -1};static int bfs(PIIs start, PIIs end) {Queue<PIIs> q = new LinkedList<PIIs>();for (int i = 0; i < n; i ++ ) Arrays.fill(dist[i],-1);dist[start.x][start.y] = 0;q.add(start);while (!q.isEmpty()){PIIs t = q.poll();for (int i = 0; i < 4; i ++ ) {int x = t.x + dx[i];int y = t.y + dy[i];if(x < 0 || x >= n || y < 0 || y >= m) continue;if(g[x][y] == '#') continue;if(dist[x][y] != -1) continue;dist[x][y] = dist[t.x][t.y] + 1;if (x == end.x && y == end.y) return dist[x][y];q.add(new PIIs(x, y));}}return -1;}public static void main(String[] args) throws IOException {BufferedReader in = new BufferedReader(new InputStreamReader(System.in));int T = Integer.parseInt(in.readLine().trim());while (T -- > 0) {String[] s = in.readLine().split(" ");n = Integer.parseInt(s[0]);m = Integer.parseInt(s[1]);for (int i = 0; i < n; i ++) {char[] charArray = in.readLine().toCharArray();for (int j = 0; j < m; j ++ ) {g[i][j] = charArray[j];if (g[i][j] == 'S') start = new PIIs(i, j);else if (g[i][j] == 'E') end = new PIIs(i, j);}}int t = bfs(start, end);if (t == -1) System.out.println("oop!");else System.out.println(t);}}
}class PIIs {int x;int y;public PIIs(int x, int y) {this.x = x;this.y = y;}
}

AcWing 1224. 交换瓶子(图论)

有 N 个瓶子,编号 1∼N,放在架子上。

比如有 5 个瓶子:

2 1 3 5 4
要求每次拿起 2 个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

1 2 3 4 5
对于这么简单的情况,显然,至少需要交换 2 次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。

输入格式
第一行包含一个整数 N,表示瓶子数量。

第二行包含 N 个整数,表示瓶子目前的排列状况。

输出格式
输出一个正整数,表示至少交换多少次,才能完成排序。

数据范围
1≤N≤10000,

输入样例1:
5
3 1 2 5 4
输出样例1:
3
输入样例2:
5
5 4 3 2 1
输出样例2:
2

思路

把每个瓶子当做是一个点
每个瓶子应该向哪个点连边呢?
向他应该在的那个位置的瓶子连边

性质:必定指向一个点,必定被一个点指向,必定成环

最终希望的结果5个自环

对于每个操作对图产生什么影响
情况1、

情况2、

所以求交换多少次,只需要求n - k,n为正数个数,k为环的个数,

代码

import java.io.*;public class Main {static final int N = 10010;static int n;static int[] b = new int[N];static boolean[] st = new boolean[N];static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));public static void main(String[] args) throws IOException {n = Integer.parseInt(in.readLine());String[] s = in.readLine().split(" ");int cnt = 0;for (int i = 1; i <= n; i ++ ) b[i] = Integer.parseInt(s[i - 1]);for (int i = 1; i <= n; i ++ ) {if (!st[i]) {cnt ++;for (int j = i; !st[j]; j = b[j])st[j] = true;}}System.out.print(n - cnt);}
}

AcWing 1113. 红与黑

有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。

你站在其中一块黑色的瓷砖上,只能向相邻(上下左右四个方向)的黑色瓷砖移动。

请写一个程序,计算你总共能够到达多少块黑色的瓷砖。

输入格式
输入包括多个数据集合。

每个数据集合的第一行是两个整数 W 和 H,分别表示 x 方向和 y 方向瓷砖的数量。

在接下来的 H 行中,每行包括 W 个字符。每个字符表示一块瓷砖的颜色,规则如下

1)‘.’:黑色的瓷砖;
2)‘#’:红色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。

当在一行中读入的是两个零时,表示输入结束。

输出格式
对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。

数据范围
1≤W,H≤20
输入样例:
6 9
…#.
…#





#@…#
.#…#.
0 0
输出样例:
45

思路

Flood fill 算法 洪水灌溉算法

dfs更方便,
bfs (最短距离)

代码

dfs版

import java.util.Arrays;
import java.util.Scanner;public class Main {static final int N = 30;static boolean[][] st = new boolean[N][N];static char[][] g = new char[N][N];static int n, m;static int[] dx = {-1, 0, 1, 0};static int[] dy = {0, 1, 0, -1};static int dfs(int x, int y) {int res = 1;st[x][y] = true;for (int i = 0; i < 4; i ++ ){int a = x + dx[i];int b = y + dy[i];if (a > n || a < 1 || b > m || b < 1) continue;if (g[a][b] != '.') continue;if (st[a][b]) continue;res += dfs(a, b);}return res;}public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNext()){//题目的行列是反的,需要注意m = in.nextInt();//列n = in.nextInt();//行if(n == 0 && m == 0) break;int x = 0, y = 0;for (int i = 1; i <= n; i ++ ) {Arrays.fill(st[i], false);  //因为st是二维数组需要一层层遍历初始化char[] c = in.next().toCharArray();for (int j = 1; j <= m; j ++ ) {g[i][j] = c[j - 1];if (g[i][j] == '@') {x = i;y = j;}}}System.out.println(dfs(x, y));}}
}

bfs版

import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;public class Main {static final int N = 25;static char[][] g = new char[N][N];static int m, n;static int[] dx = {-1, 0, 1, 0};static int[] dy = {0, 1, 0, -1};static PIIs[] p = new PIIs[N];static int bfs(int x, int y) {Queue<PIIs> q = new LinkedList<PIIs>();q.add(new PIIs(x, y));int res = 1;g[x][y] = '#';while (!q.isEmpty()) {PIIs t = q.poll();for (int i = 0; i < 4; i ++ ) {int a = t.x + dx[i];int b = t.y + dy[i];if (a > n || a < 1 || b > m || b < 1 || g[a][b] != '.') continue;res ++ ;g[a][b] = '#';q.add(new PIIs(a, b));}}return res;}public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNext()){m = in.nextInt();n = in.nextInt();if (n == 0 && m == 0) break;int x = 0;int y = 0;for (int i = 1; i <= n; i ++ ) {char[] c = in.next().toCharArray();for (int j = 1; j <= m; j ++ ) {g[i][j] = c[j - 1];if (g[i][j] == '@') {x = i;y = j;}}}System.out.println(bfs(x, y));}}
}class PIIs {int x;int y;public PIIs(int x, int y) {this.x = x;this.y = y;}
}

AcWing 1240. 完全二叉树的权值

给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是 A1,A2,⋅⋅⋅AN,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?

如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 1。

输入格式
第一行包含一个整数 N。

第二行包含 N 个整数 A1,A2,⋅⋅⋅AN。

输出格式
输出一个整数代表答案。

数据范围
1≤N≤105,
−105≤Ai≤105
输入样例:
7
1 6 5 4 3 2 1
输出样例:
2

思路

枚举每一层的起点,然后找到每一层的终点,做边界值,

代码

import java.io.*;public class Main {static final int N = 100010;static int n;static int[] a = new int[N];static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));public static void main (String[] args) throws IOException {n = Integer.parseInt(in.readLine());String[] s = in.readLine().split(" ");for (int i = 1; i <= n; i ++ ) a[i] = Integer.parseInt(s[i - 1]);int cnt = 0;long max = -N;for (int i = 1, k = 1; i <= n; i *= 2, k ++ ) {long sum = 0; for (int j = i; j < i + (1 << k - 1) && j <= n; j ++ )sum += a[j];if (sum > max){max = sum;cnt = k;}}System.out.print(cnt);}
}

AcWing 1096. 地牢大师(背一下)

你现在被困在一个三维地牢中,需要找到最快脱离的出路!

地牢由若干个单位立方体组成,其中部分不含岩石障碍可以直接通过,部分包含岩石障碍无法通过。

向北,向南,向东,向西,向上或向下移动一个单元距离均需要一分钟。

你不能沿对角线移动,迷宫边界都是坚硬的岩石,你不能走出边界范围。

请问,你有可能逃脱吗?

如果可以,需要多长时间?

输入格式
输入包含多组测试数据。

每组数据第一行包含三个整数 L,R,C 分别表示地牢层数,以及每一层地牢的行数和列数。

接下来是 L 个 R 行 C 列的字符矩阵,用来表示每一层地牢的具体状况。

每个字符用来描述一个地牢单元的具体状况。

其中, 充满岩石障碍的单元格用”#”表示,不含障碍的空单元格用”.”表示,你的起始位置用”S”表示,终点用”E”表示。

每一个字符矩阵后面都会包含一个空行。

当输入一行为”0 0 0”时,表示输入终止。

输出格式
每组数据输出一个结果,每个结果占一行。

如果能够逃脱地牢,则输出”Escaped in x minute(s).”,其中X为逃脱所需最短时间。

如果不能逃脱地牢,则输出”Trapped!”。

数据范围
1≤L,R,C≤100
输入样例:
3 4 5
S…
.###.
.##…
###.#

##.##
##…

#.###
####E

1 3 3
S##
#E#

0 0 0
输出样例:
Escaped in 11 minute(s).
Trapped!

思路

三维bfs

代码

import java.io.*;
import java.util.*;public class Main {static final int N = 110;static char[][][] g = new char[N][N][N];static Point[] p = new Point[N * N * N];static int L, R, C;static Point start;static Point end;static int[] dx = {1, -1, 0, 0, 0, 0};static int[] dy = {0, 0, 1, -1, 0, 0};static int[] dz = {0, 0, 0, 0, 1, -1};static int[][][] dist = new int[N][N][N];static Scanner in = new Scanner(System.in);static int bfs() {Queue<Point> q = new LinkedList<Point>();q.add(start);for (int i = 0; i < L; i ++ ) for (int j = 0; j < R; j ++ ) Arrays.fill(dist[i][j], -1);dist[start.x][start.y][start.z] = 0;while (!q.isEmpty()){Point t = q.poll();for (int i = 0; i < 6; i ++ ) {int x = t.x + dx[i];int y = t.y + dy[i];int z = t.z + dz[i];if (x >= L || x < 0 || y >= R || y < 0 || z >= C || z < 0) continue;if (g[x][y][z] == '#') continue;if (dist[x][y][z] != -1) continue;dist[x][y][z] = dist[t.x][t.y][t.z] + 1;if (x == end.x && y == end.y && z == end.z) return dist[x][y][z];q.add(new Point(x, y, z));}}return -1;}public static void main(String[] args) throws IOException {while (in.hasNext()) {L = in.nextInt();R = in.nextInt();C = in.nextInt();if (L == 0 && R == 0 && C == 0) continue;for (int i = 0; i < L; i ++ )for (int j = 0; j < R; j ++ ) {char[] c = in.next().toCharArray();for (int k = 0; k < C; k ++ ) {g[i][j][k] = c[k];if (g[i][j][k] == 'S') start = new Point(i, j, k);if (g[i][j][k] == 'E') end = new Point(i, j, k);}}int distance = bfs();if(distance == -1) System.out.println("Trapped!");else System.out.println("Escaped in " + distance + " minute(s).");}}
}class Point {int x, y, z;public Point(int x, int y, int z) {this.x = x;this.y = y;this.z = z;}
}

AcWing 1233. 全球变暖

你有一张某海域 N×N 像素的照片,”.”表示海洋、”#”表示陆地,如下所示:


.##…
.##…
…##.
…####.
…###.

其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 2 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。

具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:





…#…


请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

输入格式
第一行包含一个整数N。

以下 N 行 N 列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。

照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。

输出格式
一个整数表示答案。

数据范围
1≤N≤1000
输入样例1:
7

.##…
.##…
…##.
…####.
…###.

输出样例1:
1
输入样例2:
9

.##.##…
.#####…
.##.##…

.##.#…
.#.###…
.#…#…

输出样例2:
1

思路

方法1、可以先求有多个岛屿,然后求有多少个不会被完全淹没的岛屿,然后相减就可以得出被淹没的岛屿有多少个了
方法2、先求一个岛屿上一共有多少个陆地,然后求一个岛屿上一共有多少个陆地与大海相邻,然后看这两个数据是否相等,相等这说明该岛屿会被完全淹没,反之不会被淹没

代码1

import java.util.*;public class Main {static final int N = 1010;static char[][] g = new char[N][N];static boolean[][] st = new boolean[N][N];static int n;static int sum;//岛屿数static int cnt;static int[] dx = {-1, 0, 1, 0};static int[] dy = {0, -1, 0, 1};static PIIs[] p = new PIIs[N * N];static Scanner in = new Scanner(System.in);static int bfs(int x, int y) {int res = 0;Queue<PIIs> q = new LinkedList<PIIs>();st[x][y] = true;q.add(new PIIs(x, y));while (!q.isEmpty()) {PIIs t = q.poll();boolean f = true;for (int i = 0; i < 4; i ++ ) {int a = t.x + dx[i];int b = t.y + dy[i];if (a < 0 || a >= n || b < 0 || b >= n) continue;if (g[a][b] != '#') {f = false;continue;}if (st[a][b]) continue;st[a][b] = true;q.add(new PIIs(a, b));}if (f){res = 1;} }return res;}public static void main(String[] args) {n = in.nextInt();for (int i = 0; i < n; i ++ ) {char[] c = in.next().toCharArray();for (int j = 0; j < n; j ++ ) {g[i][j] = c[j];}}for (int i = 0; i < n; i ++ ) {for (int j = 0; j < n; j ++ ) {if (g[i][j] == '#' && !st[i][j]) {cnt += bfs(i, j);sum ++;} }}System.out.print(sum - cnt);}
}class PIIs {int x;int y;public PIIs(int x, int y) {this.x = x;this.y = y;}
}

代码2

import java.util.*;public class Main {static final int N = 1010;static char[][] g = new char[N][N];static boolean[][] st = new boolean[N][N];static int n;static int sum;//岛屿数static int cnt;static int[] dx = {-1, 0, 1, 0};static int[] dy = {0, -1, 0, 1};//static PIIs[] p = new PIIs[N * N];static Scanner in = new Scanner(System.in);static boolean bfs(int x, int y,int total, int bound) {Queue<PIIs> q = new LinkedList<PIIs>();st[x][y] = true;q.add(new PIIs(x, y));while (!q.isEmpty()) {PIIs t = q.poll();total ++;boolean f = false;for (int i = 0; i < 4; i ++ ) {int a = t.x + dx[i];int b = t.y + dy[i];if (a < 0 || a >= n || b < 0 || b >= n) continue;if (st[a][b]) continue;if (g[a][b] == '.') {f = true;continue;}st[a][b] = true;q.add(new PIIs(a, b));}if (f) bound ++ ;}return total == bound;}public static void main(String[] args) {n = in.nextInt();for (int i = 0; i < n; i ++ ) {char[] c = in.next().toCharArray();for (int j = 0; j < n; j ++ ) {g[i][j] = c[j];}}for (int i = 0; i < n; i ++ ) {for (int j = 0; j < n; j ++ ) {if (g[i][j] == '#' && !st[i][j]) {int total = 0, bound = 0;if (bfs(i, j, total, bound)) cnt ++;} }}System.out.print(cnt);}
}class PIIs {int x;int y;public PIIs(int x, int y) {this.x = x;this.y = y;}
}

AcWing 1207. 大臣的旅费

很久以前,T王国空前繁荣。

为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。

为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。

同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

J是T国重要大臣,他巡查于各大城市之间,体察民情。

所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。

他有一个钱袋,用于存放往来城市间的路费。

聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。

J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入格式
输入的第一行包含一个整数 n,表示包括首都在内的T王国的城市数。

城市从 1 开始依次编号,1 号城市为首都。

接下来 n−1 行,描述T国的高速路(T国的高速路一定是 n−1 条)。

每行三个整数 Pi,Qi,Di,表示城市 Pi 和城市 Qi 之间有一条双向高速路,长度为 Di 千米。

输出格式
输出一个整数,表示大臣J最多花费的路费是多少。

数据范围
1≤n≤105,
1≤Pi,Qi≤n,
1≤Di≤1000
输入样例:
5
1 2 2
1 3 1
2 4 5
2 5 4
输出样例:
135

思路

求最多花费的路费是多少,其实就是求树的直径,那么如何求树的直径呢?
从任意树内一点x出发,找到与x最远的点y,然后从点y出发,找到一个离点y最远的点z,那么zy的距离之和就是树的直径
如何存储树?
可以使用列表来存储
列表结构为:

代码

import java.util.*;public class Main {static final int N = 100010;static int n;static List[] list = new ArrayList[N];static int[] dist = new int[N];static Scanner in = new Scanner(System.in);static void dfs(int u, int father, int distance) {dist[u] = distance;for(Object x:list[u]){Node node=(Node)x;if(node.id!=father) dfs(node.id,u,distance+node.w);}}public static void main(String[] args) {n = in.nextInt();for(int i = 1; i <= n; i ++) list[i]=new ArrayList<Node>();for (int i = 0; i < n - 1; i ++) { // 循环边数int a = in.nextInt();int b = in.nextInt();int c = in.nextInt();list[a].add(new Node(b, c));list[b].add(new Node(a, c));}dfs(1, -1, 0); //第一个参数是当前节点编号,第二个参数是父节点编号,第三个是距离int u = 0, max = -1;for (int i = 1; i <= n; i ++) {if (dist[i] > max) {u = i;max = dist[i];}}dfs(u, -1, 0);u = 0;max = Integer.MIN_VALUE;for (int i = 1; i <= n; i ++ )if (dist[i] > max) {u = i;max = dist[i];}System.out.println(max * 10 + ((long)(max + 1) * max ) / 2);}
}
class Node {int id;int w;public Node(int id, int w) {this.id = id;this.w = w;}
}

AcWing 826. 单链表

实现一个单链表,链表初始为空,支持三种操作:

向链表头插入一个数;
删除第 k 个插入的数后面的数;
在第 k 个插入的数后插入一个数。
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。

输入格式
第一行包含整数 M,表示操作次数。

接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:

H x,表示向链表头插入一个数 x。
D k,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。
I k x,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
输出格式
共一行,将整个链表从头到尾输出。

数据范围
1≤M≤100000
所有操作保证合法。

输入样例:
10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6
输出样例:
6 4 6 5

代码

import java.io.*;public class Main {static final int N = 100010;static int[] e = new int[N];static int[] ne = new int[N];static int head;static int idx; /*这个参数很重要,会随着操作的次数增加而增加每一个节点都有一个对应的参数,类似存储地址,不论节点被插入还是删除,节点对应的idx都不会被改变,所以不存在重复的idx*/static void init() {head = -1;idx = 0;}static void add_to_head(int x) {e[idx] = x;ne[idx] = head;head = idx;idx ++ ;}static void add(int k, int x) {e[idx] = x;ne[idx] = ne[k];ne[k] = idx;idx ++;}static void remove(int k) {ne[k] = ne[ne[k]];}static int Int(String s) {return Integer.parseInt(s);}public static void main(String[] args) throws IOException {init();BufferedReader in = new BufferedReader(new InputStreamReader(System.in));int n = Int(in.readLine());while (n -- > 0) {String[] s = in.readLine().split(" ");if (s[0].equals("H")) {int x = Int(s[1]);add_to_head(x);}else if (s[0].equals("D")) {int k = Int(s[1]);if (k == 0) head = ne[head];else remove(k - 1);}else {int k = Int(s[1]);int x = Int(s[2]);add(k - 1, x);}}for (int i = head; i != -1; i = ne[i]) System.out.print(e[i] + " ");}}

第六讲 双指针、BFS与图论、单链表相关推荐

  1. 蓝桥杯C++ AB组辅导课 第六讲 双指针、BFS与图论 Acwing

    例题 AcWing 1238. 日志统计 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有 N 行. 其中每一行的格式是: ts id 表示在 ts 时刻编号 id ...

  2. web十六讲,表格与表单

    什么是表格 表格由<table>标签来定义 每个表格均由若干行(由tr标签定义) 每行被分为若干个单元格(由td标签定义) 标签td指表格数据及数据单元格内容 数据单元格可以包含文本.图片 ...

  3. 单链表删除所有值为x的元素_C/C++编程笔记:如何使用C++实现单链表?单链表的基本定义...

    如何弥补顺序表的不足之处? 第一次学习线性表一定会马上接触到一种叫做顺序表(顺序存储结构),经过上一篇的分析顺序表的优缺点是很显然的,它虽然能够很快的访问读取元素,但是在解决如插入和删除等操作的时候, ...

  4. 线性表详解(静态链表、单链表、双向链表、循环链表)

    目录 申明 1. 线性表的定义 2. 线性表的抽象数据类型 3. 线性表的顺序存储结构 3. 1 顺序存储定义 3. 2 顺序存储方式 3. 3 数据长度与线性表长度区别 3. 4 地址计算方法 4. ...

  5. 【考研】分清带头结点和不带头结点的单链表

    CSDN话题挑战赛第2期 参赛话题:学习笔记 前言 为分清带结点与不带头结点的单链表操作,本文以图文和表格形式描述了两者之间的区别.考研中,数据结构的单链表操作是重要考点,其中,比较常考带头结点的链表 ...

  6. 【蓝桥杯算法练习题】双指针、BFS与图论

    一.AcWing 1238. 日志统计 [题目描述] 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有NNN行. 其中每一行的格式是: ts id 表示在tstst ...

  7. 算法学习——双指针,BFS,图论

    目录 1.日志统计 题目 输入格式 输出格式 数据范围 输入样例: 输出样例: 分析 代码 2. 献给阿尔吉侬的花束 题目 输入格式 输出格式 数据范围 输入样例: 输出样例: 分析 代码 3.红与黑 ...

  8. 蓝桥杯备赛(五) 双指针,BFS与图论

    蓝桥杯备赛(五) 双指针,BFS与图论 一.双指针 1.Acwing 1238. 日志统计 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有 N 行. 其中每一行的 ...

  9. 视觉SLAM十四讲学习笔记-第六讲学习笔记总结(1)---非线性优化原理

    第六讲学习笔记如下: 视觉SLAM十四讲学习笔记-第六讲-非线性优化的状态估计问题_goldqiu的博客-CSDN博客 ​​​​​​视觉SLAM十四讲学习笔记-第六讲-非线性优化的非线性最小二乘问题_ ...

最新文章

  1. Error(s) in loading state_dict for ModelMain
  2. python编程语言能干什么-python编程语言的优势与劣势--python能干啥
  3. HTML5小游戏《智力大拼图》发布,挑战你的思维风暴
  4. 生成html页面的ftl文件,FreeMarker生成静态HTML页面的工具类FreeMarkerUtil
  5. Zookeeper的多节点集群详细启动步骤(3或5节点)
  6. 通过wifi 连接 adb 到 手机
  7. FileNotFoundError: [Errno 2] No such file or directory: 'traingingDigits/0_0.txt'
  8. 使用VS2010的Database项目模板统一管理数“.NET研究”据库对象
  9. 30hibernate_fetch_1_select
  10. 利用栈将html源码解析为节点树
  11. 男朋友就是要这个样子的
  12. macOS Monterey 12.0.1(21A559) 正式版三分区原版黑苹果镜像
  13. MIT 线性代数 Linear Algebra 25: 对称矩阵的特征值特征向量,正定矩阵
  14. FPGA:生成占空比可调的PWM波
  15. (三)Excel函数应用之逻辑函数
  16. angular中使用其他模块severs使用失败
  17. 2019-02-04~2019-02-08
  18. 阿里云开启ipv6通过appstore审核的方法
  19. PhotoShop基础入门
  20. 无光照渲染shader-二次元

热门文章

  1. win2008文件储存服务器,win server 2008 文件服务器
  2. CVPR2020 步态论文:Gait Recognition via Semi-supervised Disentangled Representation Learning to Identit
  3. html歌曲朋友圈,深夜听歌朋友圈的文案
  4. 投资理财-股市是称重机吗?
  5. 【用VBA实现Word自动打印序列号】
  6. 如和退出 百度云暗黑模式_黑暗模式的过去和现在
  7. java doc转为pdf_Java利用openoffice将doc、docx转为pdf实例代码
  8. CEO采访:从战略层面建立数据驱动型的客户体验策略
  9. 华为mate10pro计算机设置,华为mate10 pro双清教程,怎么进recovery清理数据和恢复出厂...
  10. 阿里P7架构师年薪50W,只因做到了这几点