modify code

master
algorithmzuo 3 years ago
parent 4a9fc592c3
commit 8926b00424

@ -0,0 +1,113 @@
package class_2022_12_1_week;
// 如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数 。
// 给你一个正整数 n ,请你返回区间 [1, n] 之间特殊整数的数目。
// 测试链接 : https://leetcode.cn/problems/count-special-integers/
public class Code01_CountSpecialIntegers {
public static int[] offset = {
0, // 0
1, // 1
10, // 2
100, // 3
1000,
10000,
100000, 1000000, 10000000, 100000000, 1000000000 };
public static int countSpecialNumbers(int n) {
int len = len(n);
int ans = 0;
for (int i = 1; i < len; i++) {
ans += all(i);
}
// n -> 9位数 3456789124
// 1 .....
// 2 .....
// 3 ______
int firstNumber = n / offset[len];
ans += (firstNumber - 1) * small(len - 1, 9);
ans += process(n, len, len - 1, 1 << firstNumber);
return ans;
}
// 返回n这个数字有几位
public static int len(int n) {
int ans = 0;
while (n != 0) {
ans++;
n /= 10;
}
return ans;
}
// 返回所有bits位数有几个特殊的
public static int all(int bits) {
int ans = 9;
int cur = 9;
while (--bits != 0) {
ans *= cur--;
}
return ans;
}
// bits : 8 7 6 5 4位
// candidates : 8 可能性
// bits : _ _ _ 3位
// candidates : 5 可能性
public static int small(int bits, int candidates) {
int ans = 1;
for (int i = 0; i < bits; i++, candidates--) {
ans *= candidates;
}
return ans;
}
// num : 原始数 46531 固定
// len : 原始数有几位5位固定
// rest : 还剩几位没决定,可变参数
// num : 46531
// 4 _ _ _ _
// 4 0~5
// 4 6 _ _ _
// status : 4 6 _ _ _
// 哪些数字使用了状态在status里
// 体系学习班,状态压缩的动态规划!
// int status 32位
// 9 8 7 6 5 4 3 2 1 0
// 1 0 1 0 0 0 0
// 4 6 _ _ _ 还有几个达标的!
// 哪些数字选了都在status里用一个status变量表示数字选没选(位信息)
public static int process(int num, int len, int rest, int status) {
if (rest == 0) {
return 1;
}
// 46531
// ___
// 5
// 46531 / 100 -> 465 % 10 -> 5
// 比5小的有几股0 1 2 3 4
//
// n : 454012
// 45_
// 0...
// 1...
// 2...
// 3...
// 4 _ _ _
int cur = (num / offset[rest]) % 10;
int cnt = 0;
for (int i = 0; i < cur; i++) {
if ((status & (1 << i)) == 0) {
cnt++;
}
}
int ans = cnt * small(rest - 1, 9 - (len - rest));
if ((status & (1 << cur)) == 0) {
ans += process(num, len, rest - 1, status | (1 << cur));
}
return ans;
}
}

@ -0,0 +1,75 @@
package class_2022_12_1_week;
// 给你一棵 二叉树 的根节点 root ,树中有 n 个节点
// 每个节点都可以被分配一个从 1 到 n 且互不相同的值
// 另给你一个长度为 m 的数组 queries
// 你必须在树上执行 m 个 独立 的查询,其中第 i 个查询你需要执行以下操作:
// 从树中 移除 以 queries[i] 的值作为根节点的子树
// 题目所用测试用例保证 queries[i] 不 等于根节点的值。
// 返回一个长度为 m 的数组 answer ,其中 answer[i] 是执行第 i 个查询后树的高度。
// 注意:
// 查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。
// 树的高度是从根到树中某个节点的 最长简单路径中的边数 。
// 测试链接 : https://leetcode.cn/problems/height-of-binary-tree-after-subtree-removal-queries/
public class Code02_HeightAfterSubtreeRemoval {
// 提交时不用提交这个类
public static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
}
// 提交如下方法
public static final int MAXN = 100010;
public static int[] dfn = new int[MAXN];
public static int[] deep = new int[MAXN];
public static int[] size = new int[MAXN];
public static int[] maxl = new int[MAXN];
public static int[] maxr = new int[MAXN];
public static int n;
public static int[] treeQueries(TreeNode root, int[] queries) {
n = 0;
// 每个val编号
// 每个val深度
// 每个val的子树大小
dfs(root, 0);
for (int i = 1; i <= n; i++) {
maxl[i] = Math.max(maxl[i - 1], deep[i]);
}
maxr[n + 1] = 0;
for (int i = n; i >= 1; i--) {
maxr[i] = Math.max(maxr[i + 1], deep[i]);
}
int m = queries.length;
int[] ans = new int[m];
for (int i = 0; i < m; i++) {
// queries[i] -> a
// a -> 编号x
// a -> 子树大小
// x ... 子树大小这么多范围 删掉
int leftMax = maxl[dfn[queries[i]] - 1];
int rightMax = maxr[dfn[queries[i]] + size[dfn[queries[i]]]];
ans[i] = Math.max(leftMax, rightMax);
}
return ans;
}
// n = 0 1 2 3 4 5 6 7
public static void dfs(TreeNode head, int h) {
int i = ++n;
dfn[head.val] = i;
deep[i] = h;
size[i] = 1;
if (head.left != null) {
dfs(head.left, h + 1);
size[i] += size[dfn[head.left.val]];
}
if (head.right != null) {
dfs(head.right, h + 1);
size[i] += size[dfn[head.right.val]];
}
}
}

@ -0,0 +1,70 @@
package class_2022_12_1_week;
import java.util.ArrayList;
// 给定一个无向、连通的树
// 树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。
// 给定整数 n 和数组 edges
// edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。
// 返回长度为 n 的数组 answer ,其中 answer[i] :
// 树中第 i 个节点与所有其他节点之间的距离之和。
// 测试链接 : https://leetcode.cn/problems/sum-of-distances-in-tree/
public class Code03_SumOfDistancesInTree {
public int N = 30001;
public int[] size = new int[N];
public int[] distance = new int[N];
// edges : {3,1}、{1,2}、{3,0}
// 0 : {3}
// 2 : {1}
// 3 : {1,0}
// 1 : {3,2}
public int[] sumOfDistancesInTree(int n, int[][] edges) {
ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
collect(0, -1, graph);
int[] ans = new int[n];
setAns(0, -1, 0, graph, ans);
return ans;
}
// cur : 当前节点号
// father : 当前节点的父节点
// graph : 图
public void collect(int cur, int father, ArrayList<ArrayList<Integer>> graph) {
size[cur] = 1;
distance[cur] = 0;
// 当前节点 7
// graph 7 -> {4, 8 , 13}
for (int next : graph.get(cur)) {
if (next != father) {
collect(next, cur, graph);
distance[cur] += distance[next] + size[next];
size[cur] += size[next];
}
}
}
// cur -> 当前节点!
// father -> 当前节点的父
// upDistance -> 父亲扔给cur的第二部分距离
// graph -> 图
// int[] ans 答案填写进ans
public void setAns(int cur, int father, int upDistance, ArrayList<ArrayList<Integer>> graph, int[] ans) {
ans[cur] = distance[cur] + upDistance;
for (int next : graph.get(cur)) {
if (next != father) {
setAns(next, cur, ans[cur] - distance[next] + size[0] - (size[next] << 1), graph, ans);
}
}
}
}

@ -0,0 +1,137 @@
package class_2022_12_1_week;
import java.util.Arrays;
import java.util.List;
// X轴上有一些机器人和工厂。给你一个整数数组robot其中robot[i]是第i个机器人的位置
// 再给你一个二维整数数组factory其中 factory[j] = [positionj, limitj]
// 表示第 j 个工厂的位置在 positionj ,且第 j 个工厂最多可以修理 limitj 个机器人
// 每个机器人所在的位置 互不相同。每个工厂所在的位置也互不相同
// 注意一个机器人可能一开始跟一个工厂在相同的位置
// 所有机器人一开始都是坏的,他们会沿着设定的方向一直移动
// 设定的方向要么是 X 轴的正方向,要么是 X 轴的负方向
// 当一个机器人经过一个没达到上限的工厂时,这个工厂会维修这个机器人,且机器人停止移动
// 任何时刻,你都可以设置 部分 机器人的移动方向
// 你的目标是最小化所有机器人总的移动距离
// 请你返回所有机器人移动的最小总距离
// 注意:
// 所有机器人移动速度相同
// 如果两个机器人移动方向相同,它们永远不会碰撞
// 如果两个机器人迎面相遇,它们也不会碰撞,它们彼此之间会擦肩而过
// 如果一个机器人经过了一个已经达到上限的工厂,机器人会当作工厂不存在,继续移动
// 机器人从位置 x 到位置 y 的移动距离为 |y - x|
// 1 <= robot.length, factory.length <= 100
// factory[j].length == 2
// -10^9 <= robot[i], positionj <= 10^9
// 0 <= limitj <= robot.length
// 测试数据保证所有机器人都可以被维修
// 测试链接 : https://leetcode.cn/problems/minimum-total-distance-traveled/
public class Code04_MinimumTotalDistanceTraveled {
public static long minimumTotalDistance1(List<Integer> robot, int[][] factory) {
int n = robot.size();
int m = factory.length;
robot.sort((a, b) -> a - b);
Arrays.sort(factory, (a, b) -> a[0] - b[0]);
long[][] dp = new long[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
dp[i][j] = -1;
}
}
return process1(robot, factory, n - 1, m - 1, dp);
}
public static long process1(List<Integer> robot, int[][] factory, int i, int j, long[][] dp) {
if (i < 0) {
return 0;
}
if (j < 0) {
return Long.MAX_VALUE;
}
if (dp[i][j] != -1) {
return dp[i][j];
}
long ans = process1(robot, factory, i, j - 1, dp);
long distance = 0;
for (int l = i, num = 1; l >= 0 && num <= factory[j][1]; l--, num++) {
long curAns = process1(robot, factory, l - 1, j - 1, dp);
distance += Math.abs(robot.get(l) - factory[j][0]);
if (curAns != Long.MAX_VALUE) {
ans = Math.min(ans, curAns + distance);
}
}
dp[i][j] = ans;
return ans;
}
public static long minimumTotalDistance2(List<Integer> robot, int[][] factory) {
int n = robot.size();
int m = factory.length;
robot.sort((a, b) -> a - b);
Arrays.sort(factory, (a, b) -> a[0] - b[0]);
long[][] dp = new long[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// ans = dp[i][j - 1] -> 0...i -> 0...j-1
long ans = j - 1 >= 0 ? dp[i][j - 1] : Long.MAX_VALUE;
long distance = 0;
for (int l = i, num = 1; l >= 0 && num <= factory[j][1]; l--, num++) {
long curAns = l - 1 < 0 ? 0 : (j - 1 < 0 ? Long.MAX_VALUE : dp[l - 1][j - 1]);
distance += Math.abs(robot.get(l) - factory[j][0]);
if (curAns != Long.MAX_VALUE) {
ans = Math.min(ans, curAns + distance);
}
}
dp[i][j] = ans;
}
}
return dp[n - 1][m - 1];
}
// 最优解O(N*M),目前所有题解都没有达到这个程度的
public static long minimumTotalDistance3(List<Integer> robot, int[][] factory) {
int n = robot.size();
int m = factory.length;
robot.sort((a, b) -> a - b);
Arrays.sort(factory, (a, b) -> a[0] - b[0]);
long[][] dp = new long[n][m];
long[][] deque = new long[n + 1][2];
int l = 0;
int r = 0;
// 最外的for循环一定是枚举工厂
for (int j = 0; j < m; j++) {
long add = 0;
long limit = factory[j][1];
l = 0;
r = 1;
// deque[l][0] : 加入时的下标,用来判断过期
deque[l][0] = -1;
// deque[l][1] : 加入时的指标,窗口选出最小指标 去加上当前add
deque[l][1] = 0;
for (int i = 0; i < n; i++) {
long p1 = j - 1 >= 0 ? dp[i][j - 1] : Long.MAX_VALUE;
add += Math.abs((long) robot.get(i) - (long) factory[j][0]);
if (deque[l][0] == i - limit - 1) {
l++;
}
long p2 = Long.MAX_VALUE;
if (l < r) {
long best = deque[l][1];
if (best != Long.MAX_VALUE) {
p2 = add + best;
}
}
dp[i][j] = Math.min(p1, p2);
long fill = p1 == Long.MAX_VALUE ? p1 : (p1 - add);
while (l < r && deque[r - 1][1] >= fill) {
r--;
}
deque[r][0] = i;
deque[r++][1] = fill;
}
}
return dp[n - 1][m - 1];
}
}

@ -0,0 +1,276 @@
package class_2022_12_1_week;
// 不打算讲了,非常难
// 蓝桥杯练习题
// 洛谷原题
// 等差数列的概念人人都知道
// 给定一个原始数组arr长度为N
// 并且实现如下两个操作 :
// void add(int l, int r, int a, int b) :
// 表示在arr[l...r]这个范围上,
// 从左往右依次加 : a、a + b * 1、a + b*2、...、a + b*(r-l)
// int number(int l, int r) :
// 表示arr[l...r]这一段,最少可以划分成几个等差数列
// 这两个方法都要求实现的特别高效,因为调用次数很多
// N <= 100000
// add调用次数 <= 100000
// number调用次数 <= 100000
// 测试链接 : https://www.luogu.com.cn/problem/P4243
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code提交时请把类名改成"Main"
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Code05_ArithmeticProgressionGame {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
n = (int) in.nval;
for (int i = 0; i < n; i++) {
in.nextToken();
arr[i] = (int) in.nval;
}
n--;
build(1, n, 1);
in.nextToken();
int qT = (int) in.nval;
for (int i = 0; i < qT; i++) {
in.nextToken();
String op = in.sval;
if (op.equals("A")) {
in.nextToken();
int l = (int) in.nval;
in.nextToken();
int r = (int) in.nval;
in.nextToken();
int a = (int) in.nval;
in.nextToken();
int b = (int) in.nval;
add(l, r, a, b);
} else {
in.nextToken();
int l = (int) in.nval;
in.nextToken();
int r = (int) in.nval;
out.println(number(l, r));
out.flush();
}
}
}
}
public static class Info {
public long ldiff;
public long rdiff;
public int lsplit;
public int rsplit;
public int stable;
public int size;
public Info(long a, long b, int c, int d, int e, int f) {
ldiff = a;
rdiff = b;
lsplit = c;
rsplit = d;
stable = e;
size = f;
}
}
public static final int MAXN = 100010;
public static int[] arr = new int[MAXN];
public static Info[] resident = new Info[MAXN << 2];
public static Info[] temporary = new Info[MAXN << 2];
static {
for (int i = 0; i < MAXN << 2; i++) {
resident[i] = new Info(0, 0, 0, 0, 0, 0);
temporary[i] = new Info(0, 0, 0, 0, 0, 0);
}
}
public static long[] lazy = new long[MAXN << 2];
public static int n;
private static void build(int l, int r, int rt) {
if (l == r) {
resident[rt].ldiff = arr[l] - arr[l - 1];
resident[rt].rdiff = resident[rt].ldiff;
resident[rt].lsplit = 1;
resident[rt].rsplit = 1;
resident[rt].stable = 0;
resident[rt].size = 1;
} else {
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushUp(resident, rt, rt << 1, rt << 1 | 1);
}
}
private static void pushUp(Info[] info, int f, int l, int r) {
if (l == -1 || r == -1) {
int i = l == -1 ? r : l;
info[f].ldiff = info[i].ldiff;
info[f].rdiff = info[i].rdiff;
info[f].lsplit = info[i].lsplit;
info[f].rsplit = info[i].rsplit;
info[f].stable = info[i].stable;
info[f].size = info[i].size;
} else {
boolean connect = info[l].rdiff == info[r].ldiff;
info[f].ldiff = info[l].ldiff;
info[f].rdiff = info[r].rdiff;
info[f].size = info[l].size + info[r].size;
info[f].stable = info[l].stable + info[r].stable;
if (info[l].stable == 0 && info[r].stable == 0) {
if (connect) {
info[f].lsplit = info[l].lsplit - 1;
info[f].rsplit = info[r].rsplit - 1;
info[f].stable++;
} else {
info[f].lsplit = info[f].size;
info[f].rsplit = info[f].size;
}
} else if (info[l].stable == 0) {
info[f].rsplit = info[r].rsplit;
if (connect) {
info[f].lsplit = info[l].lsplit - 1;
if (info[r].lsplit > 0) {
info[f].stable += (info[r].lsplit - 1) / 2 + 1;
}
} else {
info[f].lsplit = info[l].size + info[r].lsplit;
}
} else if (info[r].stable == 0) {
info[f].lsplit = info[l].lsplit;
if (connect) {
info[f].rsplit = info[r].rsplit - 1;
if (info[l].rsplit > 0) {
info[f].stable += (info[l].rsplit - 1) / 2 + 1;
}
} else {
info[f].rsplit = info[r].size + info[l].rsplit;
}
} else {
info[f].lsplit = info[l].lsplit;
info[f].rsplit = info[r].rsplit;
if (info[l].rsplit == 0 && info[r].lsplit == 0) {
if (connect) {
info[f].stable--;
}
} else if (info[l].rsplit == 0) {
if (connect) {
info[f].stable += (info[r].lsplit - 1) / 2;
} else {
info[f].stable += info[r].lsplit / 2;
}
} else if (info[r].lsplit == 0) {
if (connect) {
info[f].stable += (info[l].rsplit - 1) / 2;
} else {
info[f].stable += info[l].rsplit / 2;
}
} else {
int add = (info[l].rsplit + info[r].lsplit) / 2;
if (connect) {
add = (info[l].rsplit - 1) / 2 + (info[r].lsplit - 1) / 2 + 1;
}
info[f].stable += add;
}
}
}
}
private static void pushDown(int rt) {
if (lazy[rt] != 0) {
lazy[rt << 1] += lazy[rt];
resident[rt << 1].ldiff += lazy[rt];
resident[rt << 1].rdiff += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
resident[rt << 1 | 1].ldiff += lazy[rt];
resident[rt << 1 | 1].rdiff += lazy[rt];
lazy[rt] = 0;
}
}
public static void add(int l, int r, int a, int b) {
if (l > 1) {
add(l - 1, l - 1, a, 1, n, 1);
}
if (r <= n) {
add(r, r, -((long) a + ((long) (r - l)) * b), 1, n, 1);
}
if (l < r) {
add(l, r - 1, b, 1, n, 1);
}
}
public static void add(int L, int R, long V, int l, int r, int rt) {
if (L <= l && r <= R) {
resident[rt].ldiff += V;
resident[rt].rdiff += V;
lazy[rt] += V;
} else {
int m = (l + r) >> 1;
pushDown(rt);
if (L <= m) {
add(L, R, V, l, m, rt << 1);
}
if (R > m) {
add(L, R, V, m + 1, r, rt << 1 | 1);
}
pushUp(resident, rt, rt << 1, rt << 1 | 1);
}
}
public static long number(int l, int r) {
if (l == r) {
return 1;
}
query(l, r - 1, 1, n, 1);
long ans = (r - l + 2) / 2;
if (temporary[1].stable != 0) {
ans = temporary[1].stable + (temporary[1].lsplit + 1) / 2 + (temporary[1].rsplit + 1) / 2;
}
return ans;
}
public static void query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
temporary[rt].ldiff = resident[rt].ldiff;
temporary[rt].rdiff = resident[rt].rdiff;
temporary[rt].lsplit = resident[rt].lsplit;
temporary[rt].rsplit = resident[rt].rsplit;
temporary[rt].stable = resident[rt].stable;
temporary[rt].size = resident[rt].size;
} else {
int m = (l + r) / 2;
pushDown(rt);
int ll = -1;
if (L <= m) {
ll = rt << 1;
query(L, R, l, m, rt << 1);
}
int rr = -1;
if (R > m) {
rr = rt << 1 | 1;
query(L, R, m + 1, r, rt << 1 | 1);
}
pushUp(temporary, rt, ll, rr);
}
}
}

@ -2581,6 +2581,74 @@ string convert(string s, int numRows)
第051节 2022年12月第1周流行算法题目解析
如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数 。
给你一个正整数 n ,请你返回区间 [1, n] 之间特殊整数的数目。
测试链接 : https://leetcode.cn/problems/count-special-integers/
给你一棵 二叉树 的根节点 root ,树中有 n 个节点
每个节点都可以被分配一个从 1 到 n 且互不相同的值
另给你一个长度为 m 的数组 queries
你必须在树上执行 m 个 独立 的查询,其中第 i 个查询你需要执行以下操作:
从树中 移除 以 queries[i] 的值作为根节点的子树
题目所用测试用例保证 queries[i] 不 等于根节点的值。
返回一个长度为 m 的数组 answer ,其中 answer[i] 是执行第 i 个查询后树的高度。
注意:
查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。
树的高度是从根到树中某个节点的 最长简单路径中的边数 。
测试链接 : https://leetcode.cn/problems/height-of-binary-tree-after-subtree-removal-queries/
给定一个无向、连通的树
树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。
给定整数 n 和数组 edges
edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。
返回长度为 n 的数组 answer ,其中 answer[i] :
树中第 i 个节点与所有其他节点之间的距离之和。
测试链接 : https://leetcode.cn/problems/sum-of-distances-in-tree/
X轴上有一些机器人和工厂。给你一个整数数组robot其中robot[i]是第i个机器人的位置
再给你一个二维整数数组factory其中 factory[j] = [positionj, limitj]
表示第 j 个工厂的位置在 positionj ,且第 j 个工厂最多可以修理 limitj 个机器人
每个机器人所在的位置 互不相同。每个工厂所在的位置也互不相同
注意一个机器人可能一开始跟一个工厂在相同的位置
所有机器人一开始都是坏的,他们会沿着设定的方向一直移动
设定的方向要么是 X 轴的正方向,要么是 X 轴的负方向
当一个机器人经过一个没达到上限的工厂时,这个工厂会维修这个机器人,且机器人停止移动
任何时刻,你都可以设置 部分 机器人的移动方向
你的目标是最小化所有机器人总的移动距离
请你返回所有机器人移动的最小总距离
注意:
所有机器人移动速度相同
如果两个机器人移动方向相同,它们永远不会碰撞
如果两个机器人迎面相遇,它们也不会碰撞,它们彼此之间会擦肩而过
如果一个机器人经过了一个已经达到上限的工厂,机器人会当作工厂不存在,继续移动
机器人从位置 x 到位置 y 的移动距离为 |y - x|
1 <= robot.length, factory.length <= 100
factory[j].length == 2
-10^9 <= robot[i], positionj <= 10^9
0 <= limitj <= robot.length
测试数据保证所有机器人都可以被维修
测试链接 : https://leetcode.cn/problems/minimum-total-distance-traveled/
不打算讲了,非常难
蓝桥杯练习题
洛谷原题
等差数列的概念人人都知道
给定一个原始数组arr长度为N
并且实现如下两个操作 :
void add(int l, int r, int a, int b) :
表示在arr[l...r]这个范围上,
从左往右依次加 : a、a + b * 1、a + b*2、...、a + b*(r-l)
int number(int l, int r) :
表示arr[l...r]这一段,最少可以划分成几个等差数列
这两个方法都要求实现的特别高效,因为调用次数很多
N <= 100000
add调用次数 <= 100000
number调用次数 <= 100000
测试链接 : https://www.luogu.com.cn/problem/P4243

Loading…
Cancel
Save