Skip to content

Commit 0cace5b

Browse files
committed
灵茶の试炼 * 2 (无UT) & clean code
1 parent ae907ec commit 0cace5b

File tree

33 files changed

+1575
-110
lines changed

33 files changed

+1575
-110
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package base;
2+
3+
public @interface Unaccepted {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package p13;
2+
3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStreamReader;
6+
import java.util.StringTokenizer;
7+
8+
public class CF13E {
9+
static int n, m;
10+
static int mx = (int) (1e5 + 5);
11+
static int[] a;
12+
static int[] data_last;
13+
static int[] data_jump;
14+
15+
public static void main(String[] args) throws IOException {
16+
// Time limit exceeded on test 6
17+
// Scanner scanner = new Scanner(System.in);
18+
FastReader scanner = new FastReader();
19+
n = scanner.nextInt();
20+
m = scanner.nextInt();
21+
a = new int[n];
22+
for (int i = 0; i < n; i++) {
23+
a[i] = scanner.nextInt();
24+
}
25+
26+
data_last = new int[n];
27+
data_jump = new int[n];
28+
for (int i = n - 1; i >= 0; i--) {
29+
f(i);
30+
}
31+
StringBuilder ans = new StringBuilder();
32+
int last = 0;
33+
while (m-- > 0) {
34+
int op = scanner.nextInt();
35+
int p = scanner.nextInt() - 1;
36+
if (op == 0) {
37+
int v = scanner.nextInt();
38+
39+
a[p] = v;
40+
for (int i = p; i >= p - p % B; i--) {
41+
f(i);
42+
}
43+
} else {
44+
int jump = 0;
45+
for (; p < n; p = last + a[last]) {
46+
jump += data_jump[p] + 1;
47+
last = data_last[p];
48+
}
49+
String res = (last + 1) + " " + jump;
50+
ans.append(res).append(System.lineSeparator());
51+
}
52+
}
53+
System.out.println(ans);
54+
}
55+
56+
static int B = 400;
57+
58+
static void f(int i) {
59+
if (i + a[i] >= n || i / B != (i + a[i]) / B) {
60+
data_last[i] = i;
61+
data_jump[i] = 0;
62+
} else {
63+
data_last[i] = data_last[i + a[i]];
64+
data_jump[i] = data_jump[i + a[i]] + 1;
65+
// data_jump[i]++;
66+
}
67+
}
68+
69+
private static class FastReader {
70+
private final BufferedReader bufferedReader;
71+
private StringTokenizer stringTokenizer;
72+
73+
public FastReader() {
74+
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
75+
}
76+
77+
public String next() {
78+
while (stringTokenizer == null || !stringTokenizer.hasMoreElements()) {
79+
try {
80+
stringTokenizer = new StringTokenizer(bufferedReader.readLine());
81+
} catch (IOException e) {
82+
e.printStackTrace();
83+
}
84+
}
85+
return stringTokenizer.nextToken();
86+
}
87+
88+
public int nextInt() {
89+
return Integer.parseInt(next());
90+
}
91+
92+
public long nextLong() {
93+
return Long.parseLong(next());
94+
}
95+
96+
public double nextDouble() {
97+
return Double.parseDouble(next());
98+
}
99+
100+
public String nextLine() {
101+
String str = "";
102+
try {
103+
if (stringTokenizer.hasMoreTokens()) {
104+
str = stringTokenizer.nextToken("\n");
105+
} else {
106+
str = bufferedReader.readLine();
107+
}
108+
} catch (IOException e) {
109+
e.printStackTrace();
110+
}
111+
return str;
112+
}
113+
}
114+
}
115+
/*
116+
E. Holes
117+
https://codeforces.com/contest/13/problem/E
118+
119+
灵茶の试炼 2023-11-03
120+
题目大意:
121+
输入 n(1≤n≤1e5) m(1≤m≤1e5) 和长为 n 的数组 a(1≤a[i]≤n),数组下标从 1 开始。
122+
然后输入 m 个操作,输入格式如下:
123+
"0 p v" 表示把 a[p] 改成 v。
124+
"1 p" 表示从位置 p 开始向右跳,每次更新 p=p+a[p],直到 p>n。输出最后一次 <=n 的位置,以及当 p>n 时跳了多少次。
125+
(1≤p,v≤n)
126+
127+
rating 2700
128+
分块,每块大小 sqrt(n)=316。(注:改成 500 可能更快一些)
129+
把每块看成一个单独的问题,算出这一块中的每个下标 i,在跳出这个块之前,最后一次的位置 last 和跳跃次数 jump。
130+
一开始可以倒着 O(n) 递推算出所有的 last 和 jump。
131+
对于操作 0,用 O(sqrt(n)) 的时间更新 p 所在块的 last 和 jump
132+
对于操作 1,用每一块的 last 和 jump 来快速跳跃,这样只需要 O(sqrt(n)) 就可以跳出数组。
133+
注意本题有点卡常,记得把块大小设为一个常量。
134+
代码中,我的下标是从 0 开始的,输出的时候再加一。
135+
https://codeforces.com/problemset/submission/13/231055822
136+
======
137+
138+
input
139+
8 5
140+
1 1 1 1 1 2 8 2
141+
1 1
142+
0 1 3
143+
1 1
144+
0 3 4
145+
1 2
146+
output
147+
8 7
148+
8 5
149+
7 3
150+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package p730;
2+
3+
import java.util.Arrays;
4+
import java.util.Comparator;
5+
import java.util.PriorityQueue;
6+
import java.util.Scanner;
7+
8+
public class CF730I {
9+
static int n, p, s;
10+
static int[] oriA, oriB;
11+
static int[][] a; // v, i
12+
13+
public static void main(String[] args) {
14+
Scanner scanner = new Scanner(System.in);
15+
n = scanner.nextInt();
16+
p = scanner.nextInt();
17+
s = scanner.nextInt();
18+
oriA = new int[n];
19+
a = new int[n][2];
20+
for (int i = 0; i < n; i++) {
21+
oriA[i] = scanner.nextInt();
22+
a[i][0] = oriA[i];
23+
a[i][1] = i;
24+
}
25+
Arrays.sort(a, Comparator.comparingInt(o -> -o[0]));
26+
27+
int ans = 0;
28+
int[] group = new int[n];
29+
for (int i = 0; i < p; i++) {
30+
int pv = a[i][0], pi = a[i][1];
31+
ans += pv;
32+
group[pi] = 1;
33+
}
34+
PriorityQueue<int[]> pqA = new PriorityQueue<>(Comparator.comparingInt(o -> -o[0]));
35+
for (int i = p; i < a.length; i++) {
36+
pqA.add(a[i]);
37+
}
38+
39+
oriB = new int[n];
40+
PriorityQueue<int[]> pqB = new PriorityQueue<>(Comparator.comparingInt(o -> -o[0]));
41+
PriorityQueue<int[]> diff = new PriorityQueue<>(Comparator.comparingInt(o -> -o[0]));
42+
for (int i = 0; i < n; i++) {
43+
int v = oriA[i];
44+
oriB[i] = scanner.nextInt();
45+
if (group[i] == 0) {
46+
pqB.add(new int[]{oriB[i], i});
47+
} else {
48+
diff.add(new int[]{oriB[i] - v, i});
49+
}
50+
}
51+
52+
for (; s > 0; s--) {
53+
while (group[pqA.peek()[1]] > 0) {
54+
pqA.remove(); // 懒删除
55+
}
56+
while (group[pqB.peek()[1]] > 0) {
57+
pqB.remove(); // 懒删除
58+
}
59+
int[] topA = pqA.peek();
60+
int[] topB = pqB.peek();
61+
int[] topD = diff.peek();
62+
if (topB[0] > topA[0] + topD[0]) { // 直接选 b
63+
ans += topB[0];
64+
group[topB[1]] = 2;
65+
pqB.remove();
66+
} else { // 反悔一个 a 变 b(a 那边选一个更小的)
67+
ans += topA[0] + topD[0];
68+
group[topA[1]] = 1;
69+
group[topD[1]] = 2;
70+
// diff[0] = pair{oriB[topA.i] - topA.v, topA.i}
71+
// heap.Fix(&diff, 0)
72+
diff.remove();
73+
diff.add(new int[]{oriB[topA[1]] - topA[0], topA[1]});
74+
pqA.remove();
75+
}
76+
}
77+
78+
StringBuilder output = new StringBuilder();
79+
output.append(ans).append(System.lineSeparator());
80+
for (int i = 0; i < n; i++) {
81+
if (group[i] == 1) {
82+
output.append(i + 1).append(" ");
83+
}
84+
}
85+
output.append(System.lineSeparator());
86+
for (int i = 0; i < n; i++) {
87+
if (group[i] == 2) {
88+
output.append(i + 1).append(" ");
89+
}
90+
}
91+
System.out.println(output);
92+
}
93+
}
94+
/*
95+
I. Olympiad in Programming and Sports
96+
https://codeforces.com/contest/730/problem/I
97+
98+
灵茶の试炼 2024-04-05
99+
题目大意:
100+
输入 n(2≤n≤3000) p s (p≥1, s≥1, p+s≤n) 和长为 n 的数组 a(1≤a[i]≤3000),长为 n 的数组 b(1≤b[i]≤3000)。
101+
有 n 名学生,第 i 名学生的编程能力为 a[i],运动能力为 b[i]。
102+
你需要组建两支队伍:有 p 人的编程队,有 s 人的运动队。
103+
一个学生不能同时参加两支队伍。
104+
这 p+s 人的能力值之和最大是多少?学生 i 如果在编程队,他的能力值是 a[i];如果在运动队,他的能力值是 b[i]。
105+
输出最大能力值之和,编程队的学生编号,运动队的学生编号。学生编号从 1 开始。
106+
多解输出任意一解。
107+
加强版,O(nlogn):
108+
https://atcoder.jp/contests/agc018/tasks/agc018_c
109+
相似题目: 1029. 两地调度
110+
https://leetcode.cn/problems/two-city-scheduling/
111+
112+
rating 2000
113+
反悔贪心,O(nlogn)。
114+
先用编程能力最大的 p 名学生组成编程队,然后从 0 开始一个人一个人地构建运动队。
115+
分类讨论:
116+
1. 招人:从剩余学生中,选择运动能力最大的。
117+
2. 挖人:从编程队中挖一名【运动能力减编程能力】最大的学生到运动队,然后编程队再招人,从剩余学生中,选择编程能力最大的。
118+
上面这两种方法,谁能让能力总和变得更大,就用哪种方法。重复执行 s 次。
119+
这可以用三个最大堆实现,它们分别维护:
120+
1. 剩余学生中的编程能力值。
121+
2. 剩余学生中的运动能力值。
122+
3. 编程队中的【运动能力减编程能力】值。
123+
为了输出具体方案,堆中还需要记录学生编号,以及用一个数组记录第 i 个学生在哪个队伍中。
124+
https://codeforces.com/contest/730/submission/253180362
125+
======
126+
127+
Input
128+
5 2 2
129+
1 3 4 5 2
130+
5 3 2 1 4
131+
Output
132+
18
133+
3 4
134+
1 5
135+
136+
Input
137+
4 2 2
138+
10 8 8 3
139+
10 7 9 4
140+
Output
141+
31
142+
1 2
143+
3 4
144+
145+
Input
146+
5 3 1
147+
5 2 5 1 7
148+
6 3 1 6 3
149+
Output
150+
23
151+
1 3 5
152+
4
153+
154+
2 1 1
155+
100 101
156+
1 100
157+
*/

codeforces/codeforces-20/src/main/java/p1906/CF1906F.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import java.io.BufferedReader;
44
import java.io.IOException;
55
import java.io.InputStreamReader;
6-
import java.util.ArrayList;
76
import java.util.Arrays;
8-
import java.util.List;
9-
import java.util.Scanner;
107
import java.util.StringTokenizer;
118
import java.util.stream.Collectors;
129

@@ -82,7 +79,7 @@ public static void main(String[] args) {
8279
}
8380

8481
private static String solve() {
85-
LazySegmentTree seg = new LazySegmentTree(m);
82+
InfoSegmentTree seg = new InfoSegmentTree(m);
8683
seg.build(1, 1, m);
8784

8885
long[] ans = new long[q];
@@ -102,7 +99,7 @@ private static String solve() {
10299
}
103100

104101
// 线段树模板,只需要实现 mergeInfo 和 _do,其余都是固定的
105-
static class LazySegmentTree {
102+
static class InfoSegmentTree {
106103
static class Info {
107104
long ans, tot, pre, suf;
108105

@@ -126,7 +123,7 @@ Info mergeInfo(Info a, Info b) {
126123
int n;
127124
Info[] info;
128125

129-
public LazySegmentTree(int n) {
126+
public InfoSegmentTree(int n) {
130127
this.n = n;
131128
// info = new Info[4 * n];
132129
info = new Info[1 << (33 - Integer.numberOfLeadingZeros(n - 1))];

0 commit comments

Comments
 (0)