0
点赞
收藏
分享

微信扫一扫

2021年 第12届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2021.04.18】

目录

一、试题A:ASC

解法一:ASCII计算求解

解法二:类的调用

二、试题B:卡片

解法一:枚举

解法二:朴素解法

解法三:弯道超车

三、试题C:直线

解法一:直线方程集合

解法二:分式消除误差

解法三:平面几何

四、试题D:货物摆放

解法一:暴力搜索

解法二:缩放质因子

五、试题E:路径

解法一:搜索

解法二:搜索-枝剪广搜

解法三:单源最短路径-Dijkstra

解法四:单源最短路径-Floyd

六、试题F:时间显示

解法一:模拟计算

解法二:直接计算

解法三:Java-日期类API

七、试题G:最少砝码

解法一:三进制

解法二:变种三进制

八、试题H:杨辉三角形

解法一:类比单调数列

九、试题I:双向排序

解法一:去冗

解法二:填数游戏

解法三:Chtholly Tree

十、试题J:括号序列

解法一

小结


一、试题A:ASC

解法一:ASCII计算求解

package provincialGames_12_2021_1_JavaB;

public class A01_ASC { // 76
	public static void main(String[] args) {
		System.out.println('A' - 0); // 65
		System.out.println('B' - 0); // 66
		System.out.println('L' - 0); // 76
		System.out.println('Z' - 0); // 90
		System.out.println(65 + 'L' - 'A'); // 76
		System.out.println((int) 'L'); // 76
	}
}

解法二:类的调用

package provincialGames_12_2021_1_JavaB;

public class A01_ASC2 { // 76
	public static void main(String[] args) {
		new A01_ASC2().run();
	}

	void run() {
		System.out.println(65 + 'L' - 'A'); // 76
		System.out.println((int) 'L'); // 76
	}
}

二、试题B:卡片

解法一:枚举

package provincialGames_12_2021_1_JavaB;

public class B02_卡片 { // 3181
	public static int arr[] = new int[10];

	public static boolean del(int x) {
		while (x != 0) {
			arr[x % 10]--;
			if (arr[x % 10] < 0)
				return false;
			x /= 10;
		}
		return true;
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++)
			arr[i] = 2021;
		for (int i = 1; i < 5000; i++) {
			if (!del(i)) {
				System.out.println(i - 1); // 3181
				break;
			}
		}
	}
}

解法二:朴素解法

package provincialGames_12_2021_1_JavaB;

public class B02_卡片2 { // 3181
	public static void main(String[] args) {
		new B02_卡片2().run();
	}

	void run() {
		System.out.println(calc(2021)); // 3181
	}

	int calc(int upper) {
		int[] count = new int[10];
		for (int n = 1, k = 1;; k = ++n)
			do {
				if (++count[k % 10] > upper)
					return n - 1;
			} while ((k /= 10) > 0);
	}
}

解法三:弯道超车

package provincialGames_12_2021_1_JavaB;

public class B02_卡片3 { // 3181
	public static void main(String[] args) {
		new B02_卡片3().run();
	}

	void run() {
		System.out.println(calc(20)); // 99
	}

	int calc(int upper) {
		int count = 0;
		for (int n = 1, k = 1;; k = ++n) {
			do
				if (k % 10 == 1)
					count++;
			while ((k /= 10) > 0);
			if (count > upper)
				return n - 1;
		}
	}
}

三、试题C:直线

解法一:直线方程集合

package provincialGames_12_2021_1_JavaB;

import java.util.HashSet;
import java.util.Set;

public class C03_直线 { // 40257
	public static void main(String[] args) {
		new C03_直线().run();
	}

	int X = 20, Y = 21;

	void run() {
		Set<Line> set = new HashSet();
		for (int x1 = 0; x1 < X; x1++)
			for (int y1 = 0; y1 < Y; y1++)
				for (int x2 = x1; x2 < X; x2++)
					for (double y2 = 0; y2 < Y; y2++)
						if (x1 != x2) {
							double k = (y2 - y1) / (x2 - x1);
							double b = -x1 * k + y1;
							set.add(new Line(k, b));
						}
		System.out.println(set.size() + X); // 41255
	}

	class Line {
		double k, b;

		Line(double b, double k) {
			this.k = k;
			this.b = b;
		}

		@Override
		public boolean equals(Object obj) {
			return k == ((Line) obj).k && b == ((Line) obj).b;
		}

		@Override
		public int hashCode() {
			return (int) k ^ (int) b;
		}
	}
}

解法二:分式消除误差

package provincialGames_12_2021_1_JavaB;

import java.util.HashSet;
import java.util.Set;

public class C03_直线2 { // 40257
	public static void main(String[] args) {
		new C03_直线2().run();
	}

	int X = 20, Y = 21;

	void run() {
		Set<Line> set = new HashSet();
		for (int x1 = 0; x1 < X; x1++)
			for (int y1 = 0; y1 < Y; y1++)
				for (int x2 = x1; x2 < X; x2++)
					for (int y2 = 0; y2 < Y; y2++)
						if (x1 != x2) {
							Fraction k = new Fraction(y2 - y1, x2 - x1);
							Fraction b = new Fraction(y1 * (x2 - x1) - x1 * (y2 - y1), x2 - x1);
							set.add(new Line(k, b));
						}
		System.out.println(set.size() + X); // 40257
	}

	class Fraction {
		int numerator, denominator;

		Fraction(int numerator, int denominator) {
			int gcd = gcd(numerator, denominator);
			this.denominator = denominator / gcd;
			this.numerator = numerator / gcd;
		}

		int gcd(int a, int b) {
			return b == 0 ? a : gcd(b, a % b);
		}

		@Override
		public boolean equals(Object obj) {
			return this.numerator == ((Fraction) obj).numerator && this.denominator == ((Fraction) obj).denominator;
		}
	}

	class Line {
		Fraction k, b;

		Line(Fraction b, Fraction k) {
			this.k = k;
			this.b = b;
		}

		@Override
		public boolean equals(Object obj) {
			return this.k.equals(((Line) obj).k) && this.b.equals(((Line) obj).b);
		}

		@Override
		public int hashCode() {
			return k.denominator;
		}
	}
}

解法三:平面几何

package provincialGames_12_2021_1_JavaB;

public class C03_直线3 { // 40257
	public static void main(String[] args) {
		new C03_直线3().run();
	}

	int X = 20, Y = 21;

	void run() {
		int count = 0;
		boolean[][][][] marked = new boolean[X][Y][X][Y];
		for (int x1 = 0; x1 < X; x1++)
			for (int y1 = 0; y1 < Y; y1++) {
				marked[x1][y1][x1][y1] = true;
				for (int x2 = 0; x2 < X; x2++)
					for (int y2 = 0; y2 < Y; y2++) {
						if (marked[x1][y1][x2][y2])
							continue;
						int x = x1, y = y1, xOffset = x - x2, yOffset = y - y2;
						while (x >= 0 && x < X && y >= 0 && y < Y) {
							x += xOffset;
							y += yOffset;
						}
						x -= xOffset;
						y -= yOffset;
						while (x >= 0 && x < X && y >= 0 && y < Y) {
							for (int i = x - xOffset, j = y - yOffset; i >= 0 && i < X && j >= 0
									&& j < Y; i -= xOffset, j -= yOffset) {
								marked[x][y][i][j] = marked[i][j][x][y] = true;
							}
							x -= xOffset;
							y -= yOffset;
						}
						count++;
					}
			}
		System.out.println(count); // 40257
	}
}

四、试题D:货物摆放

解法一:暴力搜索

package provincialGames_12_2021_1_JavaB;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;

public class D04_货物摆放 { // 2430
	public static void main(String[] args) {
		new D04_货物摆放().run();
	}

	long n = 2021041820210418L;

	void run() {
		List<Integer> exps0 = new ArrayList();
		ArrayDeque<Integer> exps1 = new ArrayDeque();
		for (int k = 2; k <= n; k++)
			if (n % k == 0) {
				int e = 0;
				while (n % k == 0) {
					n /= k;
					e++;
				}
				exps0.add(e);
			}
		System.out.println(dfs(exps0, exps1, 0)); // 2430
	}

	int dfs(List<Integer> exps0, ArrayDeque<Integer> exps1, int cur) {
		if (cur == exps0.size()) {
			int comb = 1;
			for (int exp : exps1)
				comb *= exp + 1;
			return comb;
		}
		int ans = 0;
		for (int i = exps0.get(cur); i >= 0; i--) {
			exps1.push(i);
			ans += dfs(exps0, exps1, cur + 1);
			exps1.pop();
		}
		return ans;
	}
}

解法二:缩放质因子

package provincialGames_12_2021_1_JavaB;

import java.util.ArrayList;
import java.util.List;

public class D04_货物摆放2 { // 2430
	public static void main(String[] args) {
		new D04_货物摆放2().run();
	}

	long N = 2021041820210418L;

	void run() {
		List<Integer> exps = new ArrayList();
		for (int k = 2; k <= N; k++)
			if (N % k == 0) {
				int e = 0;
				while (N % k == 0) {
					N /= k;
					e++;
				}
				exps.add(e);
			}
		exps.sort((a, b) -> (b - a));
		int n = 1, p = 2, ans = 0;
		for (int exp : exps) {
			for (int i = 2; i * i <= p; i++)
				if (p % i == 0) {
					i = 1;
					p++;
				}
			while (exp-- > 0)
				n *= p;
			p++;
		}
		for (int a = 1; a <= n; a++)
			if (n % a == 0)
				for (int b = 1; b <= n; b++)
					if (n / a % b == 0)
						ans++;
		System.out.println(ans); // 2430
	}
}

五、试题E:路径

解法一:搜索

package provincialGames_12_2021_1_JavaB;

import java.util.ArrayList;
import java.util.List;

public class E05_路径 { // 10266837
	public static void main(String[] args) {
		new E05_路径().run();
	}

	int N = 2021;

	int[] weight = new int[N + 1];

	List<Edge>[] graph = new List[N + 1];

	boolean[] visited = new boolean[N + 1];

	void run() {
		for (int i = 1; i <= N; i++)
			graph[i] = new ArrayList();
		for (int v = 1; v < N; v++)
			for (int w = v + 1; w <= min(v + 21, N); w++) {
				graph[v].add(new Edge(w, lcm(v, w)));
				graph[w].add(new Edge(v, lcm(v, w)));
			}
		visited[1] = true;
		System.out.println(dfs(1)); // 10266837
	}

	int dfs(int v) {
		if (v == N)
			return 0;
		if (weight[v] != 0)
			return weight[v];
		int min = 0x7FFFFFFF;
		for (Edge edge : graph[v]) {
			if (visited[edge.w])
				continue;
			visited[edge.w] = true;
			min = min(min, dfs(edge.w) + edge.weight);
			visited[edge.w] = false;
		}
		return weight[v] = min;
	}

	int min(int a, int b) {
		return a < b ? a : b;
	}

	int lcm(int a, int b) {
		return a * b / gcd(a, b);
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	class Edge {
		int w, weight;

		Edge(int w, int weight) {
			this.weight = weight;
			this.w = w;
		}
	}
}

解法二:搜索-枝剪广搜

package provincialGames_12_2021_1_JavaB;

import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.List;

public class E05_路径2 { // 10266837
	public static void main(String[] args) {
		new E05_路径2().run();
	}

	int N = 2021;

	void run() {
		List<Edge>[] graph = new List[N + 1];
		long[] visited = new long[N + 1];
		for (int i = 1; i <= N; i++)
			graph[i] = new ArrayList();
		for (int v = 1; v < N; v++)
			for (int w = v + 1; w <= min(v + 21, N); w++) {
				graph[v].add(new Edge(w, lcm(v, w)));
				graph[w].add(new Edge(v, lcm(v, w)));
			}
		Queue<Vertex> queue = new PriorityQueue();
		Arrays.fill(visited, Long.MAX_VALUE);
		queue.offer(new Vertex(1, 0));
		Vertex V = null;
		while (queue.size() > 0) {
			V = queue.poll();
			if (V.v == N)
				break;
			if (V.weight >= visited[V.v])
				continue;
			visited[V.v] = V.weight;
			for (Edge edge : graph[V.v])
				queue.offer(new Vertex(edge.w, edge.weight + V.weight));
		}
		System.out.println(V.weight); // 10266837
	}

	int min(int a, int b) {
		return a < b ? a : b;
	}

	int lcm(int a, int b) {
		return a * b / gcd(a, b);
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	class Edge {
		int w, weight;

		Edge(int w, int weight) {
			this.weight = weight;
			this.w = w;
		}
	}

	class Vertex implements Comparable<Vertex> {
		int v;
		long weight;

		Vertex(int v, long weight) {
			this.weight = weight;
			this.v = v;
		}

		@Override
		public int compareTo(Vertex V) {
			return Long.compare(this.weight, V.weight);
		}
	}
}

解法三:单源最短路径-Dijkstra

package provincialGames_12_2021_1_JavaB;

import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Queue;
import java.util.List;

public class E05_路径3 { // 10266837
	public static void main(String[] args) {
		new E05_路径3().run();
	}

	int N = 2021;

	void run() {
		boolean[] marked = new boolean[N + 1];
		List<Edge>[] graph = new List[N + 1];
		long[] distTo = new long[N + 1];
		for (int i = 1; i <= N; i++) {
			graph[i] = new ArrayList();
			distTo[i] = Long.MAX_VALUE;
		}
		for (int v = 1; v < N; v++)
			for (int w = v + 1; w <= min(v + 21, N); w++) {
				graph[v].add(new Edge(w, lcm(v, w)));
				graph[w].add(new Edge(v, lcm(v, w)));
			}
		Queue<Vertex> queue = new PriorityQueue();
		queue.offer(new Vertex(1, distTo[1] = 0));
		while (queue.size() > 0) {
			Vertex V = queue.poll();
			if (marked[V.v])
				continue;
			marked[V.v] = true;
			for (Edge edge : graph[V.v])
				if (distTo[edge.w] > distTo[V.v] + edge.weight)
					queue.offer(new Vertex(edge.w, distTo[edge.w] = distTo[V.v] + edge.weight));
		}
		System.out.println(distTo[N]); // 10266837
	}

	int min(int a, int b) {
		return a < b ? a : b;
	}

	int lcm(int a, int b) {
		return a * b / gcd(a, b);
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	class Edge {
		int w, weight;

		Edge(int w, int weight) {
			this.weight = weight;
			this.w = w;
		}
	}

	class Vertex implements Comparable<Vertex> {
		int v;
		long dist;

		Vertex(int v, long dist) {
			this.dist = dist;
			this.v = v;
		}

		@Override
		public int compareTo(Vertex V) {
			return Long.compare(this.dist, V.dist);
		}
	}
}

解法四:单源最短路径-Floyd

package provincialGames_12_2021_1_JavaB;

public class E05_路径4 { // 10266837
	public static void main(String[] args) {
		new E05_路径4().run();
	}

	int N = 2021;

	void run() {
		long[][] floyd = new long[N + 1][N + 1];
		for (int v = 1; v < N; v++)
			for (int w = v + 1; w <= min(N, v + 21); w++)
				floyd[v][w] = floyd[w][v] = lcm(v, w);
		for (int k = 1; k <= N; k++)
			for (int v = 1; v <= N; v++)
				if (floyd[v][k] == 0)
					continue;
				else
					for (int w = 1; w <= N; w++)
						if (floyd[k][w] == 0)
							continue;
						else if (floyd[v][w] == 0 || floyd[v][k] + floyd[k][w] < floyd[v][w])
							floyd[v][w] = floyd[v][k] + floyd[k][w];
		System.out.println(floyd[1][N]); // 10266837
	}

	long min(int a, int b) {
		return a < b ? a : b;
	}

	int lcm(int a, int b) {
		return a * b / gcd(a, b);
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
}

六、试题F:时间显示

解法一:模拟计算

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class F06_时间显示 {
	public static String tos(long x) {
		if (x < 10)
			return "0" + x;
		else
			return "" + x;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		n %= (1000 * 60 * 60 * 24);
		n /= 1000;
		System.out.println(tos(n / 3600) + ":" + tos((n / 60) % 60) + ":" + tos(n % 60));
	}
}

解法二:直接计算

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class F06_时间显示3 {
	public static void main(String[] args) {
		new F06_时间显示3().run();
	}

	void run() {
		long t = new Scanner(System.in).nextLong();
		System.out.printf("%02d:%02d:%02d", t / 3600000 % 24, t / 60000 % 60, t / 1000 % 60);
	}
}

解法三:Java-日期类API

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class F06_时间显示3 {
	public static void main(String[] args) {
		new F06_时间显示3().run();
	}

	void run() {
		System.out.println(LocalTime.MIDNIGHT.plusSeconds(new Scanner(System.in).nextLong() / 1000)
				.format(DateTimeFormatter.ISO_LOCAL_TIME));
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		System.out.println(LocalTime.MIDNIGHT.plusSeconds(n / 1000).format(DateTimeFormatter.ISO_LOCAL_TIME));
	}
}

七、试题G:最少砝码

解法一:三进制

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class G07_最少砝码 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long x = sc.nextLong();
		long sum = 1, cur = 1;
		while (sum < x) {
			sum += Math.pow(3, cur);
			cur++;
		}
		System.out.println(cur);
	}
}

解法二:变种三进制

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class G07_最少砝码2 {
	public static void main(String[] args) {
		new G07_最少砝码2().run();
	}

	void run() {
		long N = new Scanner(System.in).nextLong(), ans = 1;
		for (long pow3 = 1; pow3 < N; pow3 = pow3 * 3 + 1, ans++)
			;
		System.out.println(ans);
	}
}

八、试题H:杨辉三角形

解法一:类比单调数列

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class H08_杨辉三角形 {
	public static void main(String[] args) {
		new H08_杨辉三角形().run();
	}

	int N;

	void run() {
		N = new Scanner(System.in).nextInt();
		if (N == 1)
			System.out.println(1);
		else {
			long ans = (N + 1L) * N / 2 + 2;
			for (int m = 2; m < 16; m++) {
				int start = m * 2, end = N;
				while (start <= end) {
					int mid = start + end >> 1;
					if (C(mid, m) == N) {
						ans = min(ans, (mid + 1L) * mid / 2 + m + 1);
						break;
					}
					if (C(mid, m) > N)
						end = mid - 1;
					else
						start = mid + 1;
				}
			}
			System.out.println(ans);
		}
	}

	long min(long a, long b) {
		return a < b ? a : b;
	}

	long C(int n, int m) {
		long num = 1;
		for (int nm = 1; nm <= m; n--, nm++)
			if ((num = num * n / nm) > N)
				return num;
		return num;
	}
}

九、试题I:双向排序

解法一:去冗

​package provincialGames_12_2021_1_JavaB;

import java.io.*;
import java.util.*;

public class I09_双向排序 {
	public static void main(String[] args) {
		new I09_双向排序().run();
	}

	void run() {
		InputReader in = new InputReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.readInt(), m = in.readInt();
		Deque<Step> deque = new ArrayDeque();
		deque.push(new Step(1, 1));
		while (m-- > 0) {
			int p = in.readInt();
			int q = in.readInt();
			while (deque.size() > 0 && deque.peek().p == p)
				if (p == 0)
					q = max(q, deque.pop().q);
				else
					q = min(q, deque.pop().q);
			deque.push(new Step(p, q));
		}
		Integer[] ans = new Integer[n];
		for (int i = 0; i < n; i++)
			ans[i] = i + 1;
		deque.pollLast();
		while (deque.size() > 0) {
			Step step = deque.pollLast();
			if (step.p == 0)
				Arrays.sort(ans, 0, step.q, (a, b) -> (b - a));
			else
				Arrays.sort(ans, step.q - 1, n);
		}
		for (int i = 0; i < n; i++) {
			out.print(ans[i]);
			out.print(' ');
		}
		out.flush();
	}

	int max(int a, int b) {
		return a > b ? a : b;
	}

	int min(int a, int b) {
		return a < b ? a : b;
	}

	class Step {
		int p, q;

		Step(int p, int q) {
			this.p = p;
			this.q = q;
		}
	}

	class InputReader {
		BufferedReader reader;
		StringTokenizer token;

		InputReader(InputStream in) {
			this.reader = new BufferedReader(new InputStreamReader(in));
		}

		String read() {
			while (token == null || !token.hasMoreTokens()) {
				try {
					token = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return token.nextToken();
		}

		int readInt() {
			return Integer.parseInt(read());
		}
	}
}

解法二:填数游戏

package provincialGames_12_2021_1_JavaB;

import java.io.*;
import java.util.*;

public class I09_双向排序2 {
	public static void main(String[] args) {
		new I09_双向排序2().run();
	}

	void run() {
		InputReader in = new InputReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.readInt(), m = in.readInt(), top;
		Step[] stack = new Step[m + 1];
		for (top = 0; m-- > 0;) {
			int p = in.readInt();
			int q = in.readInt();
			if (p == 0) {
				while (top > 0 && stack[top].p == p)
					q = max(q, stack[top--].q);
				while (top > 1 && stack[top - 1].q <= q)
					top -= 2;
				stack[++top] = new Step(p, q);
			} else if (top > 0) {
				while (top > 0 && stack[top].p == p)
					q = min(q, stack[top--].q);
				while (top > 1 && stack[top - 1].q >= q)
					top -= 2;
				stack[++top] = new Step(p, q);
			}
		}
		int[] ans = new int[n + 1];
		int a = n, l = 0, r = n - 1;
		for (int i = 1; i <= top; i++)
			if (stack[i].p == 0)
				while (r >= stack[i].q && l <= r)
					ans[r--] = a--;
			else
				while (l + 1 < stack[i].q && l <= r)
					ans[l++] = a--;
		if ((top & 1) == 1)
			while (l <= r)
				ans[l++] = a--;
		else
			while (l <= r)
				ans[r--] = a--;
		for (int i = 0; i < n; i++) {
			out.print(ans[i]);
			out.print(' ');
		}
		out.flush();
	}

	int max(int a, int b) {
		return a > b ? a : b;
	}

	int min(int a, int b) {
		return a < b ? a : b;
	}

	class Step {
		int p, q;

		Step(int p, int q) {
			this.p = p;
			this.q = q;
		}
	}

	class InputReader {
		BufferedReader reader;
		StringTokenizer token;

		InputReader(InputStream in) {
			this.reader = new BufferedReader(new InputStreamReader(in));
		}

		String read() {
			while (token == null || !token.hasMoreTokens()) {
				try {
					token = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return token.nextToken();
		}

		int readInt() {
			return Integer.parseInt(read());
		}
	}
}

解法三:Chtholly Tree

package provincialGames_12_2021_1_JavaB;

import java.io.*;
import java.util.*;

public class I09_双向排序3 {
	public static void main(String[] args) {
		new I09_双向排序3().run();
	}

	void run() {
		InputReader in = new InputReader(System.in);
		int n = in.readInt(), m = in.readInt();
		Node[] root = new Node[n + 1];
		int[] P = new int[n + 1];
		Range lower, temp, now;
		lower = now = new Range(0);
		for (int i = 1; i <= n; i++) {
			now = now.next = new Range(i);
			root[i] = build(1, n, i);
		}
		now.next = new Range(n + 1);
		while (m-- > 0) {
			int p = in.readInt();
			int L = in.readInt();
			int R = n;
			if (p == 0) {
				R = L;
				L = 1;
			}
			now = lower;
			while (now.next.L <= L)
				now = now.next;
			if (L > now.L) {
				root[L] = split(root[now.L], L - now.L, P[now.L]);
				now = now.next = new Range(L, now.next);
			}
			temp = now;
			Node pq = null;
			while (now.L <= R) {
				if (now.next.L > R + 1)
					root[R + 1] = split(root[now.L], R + 1 - now.L, P[R + 1] = P[now.L]);
				pq = merge(pq, root[now.L]);
				now = now.next;
			}
			if (now.L == R + 1)
				temp.next = now;
			else
				temp.next = new Range(R + 1, now);
			root[L] = pq;
			P[L] = p;
		}
		StringBuilder ans = new StringBuilder();
		while ((lower = lower.next).L <= n)
			buildAns(ans, root[lower.L], 1, n, P[lower.L]);
		System.out.println(ans);
	}

	Node split(Node tree, int k, int p) {
		if (tree == null)
			return null;
		Node split = new Node(0);
		if (p == 0) {
			int K = K(tree.right);
			if (k <= K) {
				if (k != K)
					split.right = split(tree.right, k, p);
				split.left = tree.left;
				tree.left = null;
			} else
				split.left = split(tree.left, k - K, p);
		} else {
			int K = K(tree.left);
			if (k <= K) {
				if (k != K)
					split.left = split(tree.left, k, p);
				split.right = tree.right;
				tree.right = null;
			} else
				split.right = split(tree.right, k - K, p);
		}
		split.k = tree.k - k;
		tree.k = k;
		return split;
	}

	Node merge(Node tree1, Node tree2) {
		if (tree1 == null)
			return tree2;
		if (tree2 != null) {
			tree1.k += K(tree2);
			tree1.left = merge(tree1.left, tree2.left);
			tree1.right = merge(tree1.right, tree2.right);
		}
		return tree1;
	}

	Node build(int L, int R, int k) {
		if (L == R)
			return new Node(1);
		Node node = new Node(1);
		int mid = L + R >> 1;
		if (k <= mid)
			node.left = build(L, mid, k);
		else
			node.right = build(mid + 1, R, k);
		return node;
	}

	void buildAns(StringBuilder builder, Node root, int L, int R, int p) {
		if (root == null)
			return;
		if (L == R)
			builder.append(L).append(' ');
		else {
			int mid = L + R >> 1;
			if (p == 0) {
				buildAns(builder, root.right, mid + 1, R, p);
				buildAns(builder, root.left, L, mid, p);
			} else {
				buildAns(builder, root.left, L, mid, p);
				buildAns(builder, root.right, mid + 1, R, p);
			}
		}
	}

	int K(Node node) {
		return node == null ? 0 : node.k;
	}

	class Range {
		int L;

		Range next;

		Range(int L) {
			this(L, null);
		}

		Range(int L, Range next) {
			this.L = L;
			this.next = next;
		}
	}

	class Node {
		int k = 1;

		Node left, right;

		Node(int k) {
			this.k = k;
		}
	}

	class InputReader {
		BufferedReader reader;
		StringTokenizer token;

		InputReader(InputStream in) {
			this.reader = new BufferedReader(new InputStreamReader(in));
		}

		String read() {
			while (token == null || !token.hasMoreTokens()) {
				try {
					token = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return token.nextToken();
		}

		int readInt() {
			return Integer.parseInt(this.read());
		}
	}
}

十、试题J:括号序列

解法一

package provincialGames_12_2021_1_JavaB;

import java.util.Scanner;

public class J10_括号序列 {
	public static void main(String[] args) {
		new J10_括号序列().run();
	}

	int mod = 1000000007;

	void run() {
		byte[] line = new byte[5555];
		try {
			int n = System.in.read(line, 1, 5050) - 1;
			System.out.println(calc(line, n, false) * calc(line, n, true) % mod);
		} catch (java.io.IOException e) {
			e.fillInStackTrace();
		}
	}

	long calc(byte[] str, int n, boolean turn) {
		if (turn)
			reverse(str, n);
		int[][] dp = new int[n + 1][n + 2];
		int opening = 0;
		dp[0][0] = 1;
		for (int i = 1; i <= n; i++) {
			if (str[i] == '(') {
				for (int j = 1; j <= n; j++)
					dp[i][j] = dp[i - 1][j - 1];
				opening++;
			} else {
				dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
				for (int j = 1; j <= n; j++)
					dp[i][j] = (dp[i][j - 1] + dp[i - 1][j + 1]) % mod;
				if (opening > 0)
					opening--;
			}
		}
		return dp[n][opening];
	}

	void reverse(byte[] arr, int n) {
		for (int i = 1, j = n; i <= j; i++, j--) {
			byte temp = (byte) (arr[i] ^ 1);
			arr[i] = (byte) (arr[j] ^ 1);
			arr[j] = temp;
		}
	}
}

小结

举报

相关推荐

0 条评论