Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package base;
2+
3+
public @interface Unaccepted {
4+
}
Lines changed: 150 additions & 0 deletions
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+
*/
Lines changed: 157 additions & 0 deletions
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

Lines changed: 3 additions & 6 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /