提交 300f98cc 编写于 作者: qq_36480062's avatar qq_36480062

c

上级 86de54de
......@@ -107,7 +107,9 @@ public class 木棒 {
});
len = 1;
while (true) {
//只枚举约数
if (sum % len == 0 && dfs(0, 0, 0)) {
//
System.out.println(len);
break;
}
......@@ -128,7 +130,7 @@ public class 木棒 {
}
if (s == len) return dfs(u + 1, 0, 0);
//按照组合数枚举
//按照组合数枚举,不考虑顺序
for (int i = start; i < n; i++) {
if (st[i]) continue;
if (s + w[i] > len) continue;//可行性剪枝,超长了
......
......@@ -53,6 +53,7 @@ import java.util.Scanner;
* 如何当两个队列都非空的时候,先对较小的那个队列出队做BFS,以减小状态的增加数量,
* 并且如果两个队头元素的步数之和超过了10,就可以剪枝直接返回了。
* 状态的转换需要考虑从状态x能够转换到哪些状态,因为字符串较短这里直接暴力搜索就可以解决了,
* 过5个数据
*/
//@SuppressWarnings("all")
public class 字串变换 {
......@@ -97,11 +98,12 @@ public class 字串变换 {
}
private static int extend(ArrayDeque<String> q, HashMap<String, Integer> da, HashMap<String, Integer> db) {
int star = 0;
int j = 0;
for (int k = 0, sk = q.size(); k < sk; k++) {
String t = q.poll();
String t = q.pollFirst();
if (t != null) {
int star = 0;
int j = 0;
for (int i = 0; i < n; i++) {
star = 0;
j = 0;
......
package DFS.迭代加深;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_30277239/article/details/105771948
* 如下图所示,有一个“#”形的棋盘,上面有1,2,3三种数字各8个。
* 给定8种操作,分别为图中的A~H。
* 这些操作会按照图中字母和箭头所指明的方向,把一条长为8的序列循环移动1个单位。
* 例如下图最左边的“#”形棋盘执行操作A后,会变为下图中间的“#”形棋盘,再执行操作C后会变成下图最右边的“#”形棋盘。
* 给定一个初始状态,请使用最少的操作次数,使“#”形棋盘最中间的8个格子里的数字相同。
* 输入格式
* 输入包含多组测试用例。
* 每个测试用例占一行,包含24个数字,表示将初始棋盘中的每一个位置的数字,按整体从上到下,同行从左到右的顺序依次列出。
* 输入样例中的第一个测试用例,对应上图最左边棋盘的初始状态。
* 当输入只包含一个“0”的行时,表示输入终止。
* 输出格式
* 每个测试用例输出占两行。
* 第一行包含所有移动步骤,每步移动用大写字母“A~G”中的一个表示,字母之间没有空格,如果不需要移动则输出“No moves needed”。
* 第二行包含一个整数,表示移动完成后,中间8个格子里的数字。
* 如果有多种方案,则输出字典序最小的解决方案。
* 输入样例:
* 1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
* 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
* 0
* 输出样例:
* AC
* 2
* DDHH
* 2
* 分析:
* 本题同样考察IDA*,每次有八种本题的操作可以选择,一旦一开始选择了错误的方向,
* 便可能搜索到很多无用的较深分支,因此可以在迭代加深的基础上使用估价函数。
* 分析最终状态,最终状态是中间八个数都是同一个数字,而每次操作都会使得中间八个数中的一个数出去,
* 外面的一个数进来,也就是改变中间的一个数字。设x是中间八个数的众数,出现了f次,
* 则至少要经过8 - f次操作才能够把中间所有的数都变成x,这就是估价函数的定义,即f = 8 - 众数出现的次数。
* 基本框架已经解决了,下面要解决的是如果存储和操作这个井字形棋盘。首先,按照题目的输入格式给这24个数编号,得到下面的图:
* 0 1
* 2 3
* 4 5 6 7 8 9 10
* 11 12
* 13 14 15 16 17 18 19
* 20 21
* 22 23
* 然后用个二维数组g存储各种操作会操作的数字,比如A会操作0,2,6,11,15,20,22,
* 其他的也类似,最后得到一个八行七列的数组,每次操作只需要将对应的数组第一个数搬到末尾即可。
* 同时,用cen[8]存储中间的8个数的下标,用q存储编号0到23这24个数的具体数值。
* 这里还有个重要的剪枝,就是每次操作前要注意不能操作上一次的反操作,比如上一次进行了A操作,
* 再次进行F操作就将棋盘还原了,肯定不是最优的操作,因此,用op数组存下各个操作的反操作编号,
* 每次操作前判断下即可,dfs完恢复现场时也是用此次进行操作的反操作去恢复的。
* 代码的实现比较简单,唯一需要注意的是数组g存储的只是各个位置的元素在q中的编号,
* 因此进行各种操作的时候,操作的是q数组里面的值,g数组里面的编号始终是不变的。
* 按照字典序A-H暴力搜索
* 搜索层数非常深,范围很广
* 但答案层数不会很深
* 估价函数:统计中间出现次数最多的数字的次数,作为估价,
* 比如出现了cnt次,那么8-cnt就是估价排序的...
* 优化,上一次拉A,那么下一次不能拉F,抵消了
*/
public class 回转游戏 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
q[0] = sc.nextInt();
if (q[0] == 0) break;
for (int i = 1; i < N; i++) {
q[i] = sc.nextInt();
}
int depth = 0;
while (!dfs(0, depth, -2)) depth++;
if (depth == 0) System.out.println("No moves needed");
else {
for (int i = 0; i < depth; i++) {
System.out.print((char) (path[i] + 'A'));
}
System.out.println();
}
System.out.println(q[6]);
}
}
static int N = 24;
static int[][] op = {{0, 2, 6, 11, 15, 20, 22},
{1, 3, 8, 12, 17, 21, 23},
{10, 9, 8, 7, 6, 5, 4},
{19, 18, 17, 16, 15, 14, 13},
{23, 21, 17, 12, 8, 3, 1},
{22, 20, 15, 11, 6, 2, 0},
{13, 14, 15, 16, 17, 18, 19},
{4, 5, 6, 7, 8, 9, 10}};
static int[] option = {5, 4, 7, 6, 1, 0, 3, 2};
static int[] center = {6, 7, 8, 11, 12, 15, 16, 17};
static int[] q = new int[N];
static int[] path = new int[100];
static boolean dfs(int depth, int max_depth, int last) {
if (depth + f() > max_depth) return false;
if (f() == 0) return true;
for (int i = 0; i < 8; i++) {
if (last != option[i]) {
option(i);
path[depth] = i;
if (dfs(depth + 1, max_depth, i)) return true;
option(option[i]);
}
}
return false;
}
static int f() {
int[] sum = {0, 0, 0, 0};
for (int i = 0; i < 8; i++) {
sum[q[center[i]]]++;
}
int s = 0;
for (int i = 1; i <= 3; i++) {
s = Math.max(sum[i], s);
}
return 8 - s;
}
static void option(int x) {
int t = q[op[x][0]];
for (int i = 0; i < 6; i++) {
q[op[x][i]] = q[op[x][i + 1]];
}
q[op[x][6]] = t;
}
}
package DFS.迭代加深;
import java.util.Arrays;
import java.util.Scanner;
/**
......@@ -43,15 +44,18 @@ import java.util.Scanner;
* (n + 2n + 3n + ... (n-1)n) - (1 + 4 + 9 + (n - 1)^2) = (n-1)n*n / 2 - n(n-1)(2n-1) / 6 = n(n-1)(n+1) / 6,
* 当n = 15时,14 * 15 * 16 / 6 = 960。要想搜四层状态,就要搜索接近1000^4这么多种状态,
* 显然无法承受,所以可以双向DFS将状态数降低到1000^2级别。使用IDA*则能够更快的解决问题。
*
* 我们知道,估价函数的值是不会超过当前状态离目标状态的真实距离的,所以一旦已搜索的深度u加上估价函数的值超过了设定的深度,
* 就不必继续搜索了。如果每次只能移动一个元素,我们可以用每个元素离最终位置的距离作为估价函数,但是现在是批量移动元素。
* 比如1 2 3 4 5,将2 3移动到4的后面得到1 4 2 3 5,可以发现1的后继、4的后继、3的后继都改变了,而其它元素的后继未变,
* 实际上,每次移动最多能改变三个元素的后继,所谓的后继就是这个元素的下一个元素。我们要实现的最终状态是每个元素的后继都比当前元素多1,
* 就说明有序了。设估价函数为错误后继的对数,注意这里的错误后继与逆序对并不是一个概念。只要一个元素的后一个元素不是比它大1的元素,
* 就应该记入错误后继。既然因此移动只能改变3个元素的后继,那么当前错误后继对数为cnt时,至少需要cnt / 3上取整次移动才能将序列恢复为有序。
* 实际上,每次移动最多能改变三个元素的后继,所谓的后继就是这个元素的下一个元素。
* 我们要实现的最终状态是每个元素的后继都比当前元素多1,
* 就说明有序了。设估价函数为错误后继的对数,注意这里的错误后继与逆序对并不是一个概念。
* 只要一个元素的后一个元素不是比它大1的元素,
* 就应该记入错误后继。既然因此移动只能改变3个元素的后继,那么当前错误后继对数为cnt时,
* 至少需要cnt / 3上取整次移动才能将序列恢复为有序。
* 估价函数f就等于(cnt + 2) / 3,这里加上2是为了上取整。
* 下面要做的,就是在dfs里枚举每次取的序列的长度,起点位置以及移动到哪个位置后,比如 1 2 3 4 5,长度为1时,起点是下标为0的位置,也就是元素1,
* 下面要做的,就是在dfs里枚举每次取的序列的长度,起点位置以及移动到哪个位置后,
* 比如 1 2 3 4 5,长度为1时,起点是下标为0的位置,也就是元素1,
* 将它移动到下标为3的后面就得到了2 3 4 1 5,。长度为1的序列移动规律可能不太明显,
* 来看个更长的序列,1 2 3 4 5 6 7 8移动2 3 4到6的后面得到1 5 6 2 3 4 7 8,可以发现只是将2 3 4右移了2个位置。
* 这里我使用了一种常见的移动元素的策略,就是先将2 3 4反转,再将5 6反转,最后将这个5个元素所在区间的所有元素反转,
......@@ -80,10 +84,19 @@ public class 排书 {
return false;
if (f() == 0) return true;
for (int len = 1; len <= n; len++) {
for (int l = 0; l + len <= n; l++) {
for (int l = 0; l + len - 1 < n; l++) {
int r = l + len - 1;
for (int k = r + 1; k < n; k++) {
w[depth] = Arrays.copyOf(q, q.length);
int y = l;
for (int x = r + 1; x <= k; x++, y++) {
q[y] = w[depth][x];
}
for (int x = l; x <= r; x++, y++) {
q[y] = w[depth][x];
}
if (dfs(depth + 1, max_depth)) return true;
q = Arrays.copyOf(w[depth], q.length);
}
}
}
......
......@@ -36,9 +36,9 @@ public class 重复性剪枝 {
dfs(u + 1, s, w);
}
static void ddf(int s, int cnt, int pos) {
if (s > sum || cnt > k) return;
if (s == sum && cnt == k) {
static void ddf(int u, int cnt, int pos) {
if (u > sum || cnt > k) return;
if (u == sum && cnt == k) {
te++;
return;
}
......@@ -46,7 +46,7 @@ public class 重复性剪枝 {
for (int i = pos; i < n; i++) {
if (!vis[i]) {
vis[i] = true;
ddf(s + a[i], cnt + 1, i + 1);
ddf(u + a[i], cnt + 1, i + 1);
vis[i] = false;
}
}
......
......@@ -42,8 +42,10 @@ import static java.lang.System.in;
*/
public class kruskal {
public static void main(String[] args) throws IOException {
for (int i = 0; i < par.length; i++) {
par[i] = i;
}
PriorityQueue<node> q = new PriorityQueue<node>();
//Scanner sc = new Scanner(System.in);
n = nextInt();
m = nextInt();
int a, b, c;
......@@ -91,12 +93,6 @@ public class kruskal {
static int[] par = new int[200005];
static {
for (int i = 0; i < par.length; i++) {
par[i] = i;
}
}
static void union(int a, int b) {
int aroot = find(a);
int broot = find(b);
......
......@@ -83,7 +83,7 @@ public class 可达性统计 {
d[b]++;
}
toposort();
for (int i = n - 1; i >= 0; i--) {
for (int i = n - 1; i >= 0; i--) {//从后往前,
int j = q[i];
f[j].set(j);
for (int k = h[j]; k != 0; k = ne[k]) {
......@@ -125,13 +125,14 @@ public class 可达性统计 {
if (d[i] == 0) {
q[++tt] = i;
}
}
}//入度为0的点加入队列
while (hh <= tt) {
int t = q[hh++];//出队
for (int i = h[t]; i != 0; i = ne[i]) {
int j = e[i];
--d[j];
if (d[j] == 0) {
if (d[j] == 0) {//入度为0加入队列
q[++tt] = j;
}
}
......
......@@ -14,7 +14,6 @@ import java.util.StringTokenizer;
* 2 4
* 输出样例:
* Yes
*
*/
public class 二分图判定 {
public static void main(String[] args) throws IOException {
......@@ -72,7 +71,7 @@ public class 二分图判定 {
color[u] = c;
for (int i = h[u]; i != 0; i = ne[i]) {
int j = e[i];
if (color[j] == 0) {//该点未被访问过
if (color[j] == 0) {//该点未被访问过,3-1=2 3-2=1 2和1为不同颜色
if (!dfs(j, 3 - c)) return true;
} else if (color[j] == c) return false;
//u点和j点,也就是一条边的两边的颜色相同,我们就说他不是二分图
......
......@@ -11,9 +11,11 @@ import java.util.StringTokenizer;
* 答案0-10^9之间,看是否具有二分性质
* check()怎么写至关重要
* 也就是把答案区间分成两段,最优解把答案区间分成两段,一边具备这个性质,另一边不具备这个性质
* 把大于mid边都删除,对应题目就是,把所有仇恨值大于某个值的两个罪犯,分到两个监狱,是不是二分图,可不可行
* 把大于mid边都删除,对应题目就是,把所有仇恨值大于某个值的两个罪犯,分到两个监狱,
* 是不是二分图,可不可行
* 如果可行那么最优解一定小于等于mid
* 对于最优解的右边一定也是满足性质,因为最优解释最小的那个点,选择大于最优解的值,去掉一些边,肯定还是二分图
* 对于最优解的右边一定也是满足性质,因为最优解释最小的那个点,
* 选择大于最优解的值,去掉一些边,肯定还是二分图
* 答案区间左边为不满足二分性质,
*/
public class 关押罪犯 {
......
......@@ -5,6 +5,15 @@ import java.util.Scanner;
/**
* https://blog.csdn.net/chrisblogtk/article/details/51099957?utm_source=blogxgwz7
* 战争时期,前线有n 个哨所,每个哨所可能会与其他若干个哨所之间有通信联系。信使负责 在哨所之间传递信息,
* 当然,这是要花费一定时间的(以天为单位)。指挥部设在第一个哨所。当指挥部下达一个命令后,
* 指挥部就派出若干个信使向与指挥部相连的哨所送信。当一个哨所接到信后,
* 这个哨所内的信使们也以同样的方式向其他哨所送信。直至所有n个哨所全部接到命令后,
* 送信才算成功。因为准备充足,每个哨所内都安排了足够的信使(如果一个哨所与其他k个哨所有通信联系的话,这个哨所内至少会配备k个信使)。
* 现在总指挥请你编一个程序,计算出完成整个送信过程最短需要多少时间。
* 第 1 行有两个整数 n 和 m,中间用 1 个空格隔开,分别表示有 n 个 哨所和m条通信线路。1<=n<=100。
* 第 2 至 m+1 行:每行三个整数 i、j、k,中间用 1 个空格隔开,表示第 i 个和第 j 个哨所 之间存在通信线路,且这条线路要花费k 天。
* 仅一个整数,表示完成整个送信过程的最短时间。如果不是所有的 哨所都能收到信,就输出-1。
* 对于每个点的时间等于他到指挥部的最短距离
* 1号点是指挥部
* 如果有点无法到达输出-1
......
......@@ -5,6 +5,32 @@ import java.util.Scanner;
/**
* https://blog.csdn.net/a1097304791/article/details/88971315
* 你想娶酋长的女儿,但酋长要求你给一定数额金钱的聘礼。除了金钱外,酋长也允许你用部落里其他人的某物品加上一点钱作为聘礼。
* 而其他人的物品也可以通过指定的另外一些人的某物品加上一些金钱获得。部落里的每个人有一个等级。
* 你的整个交易过程涉及的人的等级只能在一个限定的差值内。问你最少需要多少金钱才能娶到酋长女儿。假定每个人只有一个物品。
* Input
* 输入第一行是两个整数M,N(1 <= N <= 100),依次表示地位等级差距限制和物品的总数。接下来按照编号从小到大依次给出了N个物品的描述。
* 每个物品的描述开头是三个非负整数P、L、X(X < N),依次表示该物品的价格、主人的地位等级和替代品总数。
* 接下来X行每行包括两个整数T和V,分别表示替代品的编号和"优惠价格"。
* Output
* 输出最少需要的金币数。
* Examples
* Sample Input
* 1 4
* 10000 3 2
* 2 8000
* 3 5000
* 1000 2 1
* 4 200
* 3000 2 1
* 4 200
* 50 2 0
* <p>
* Sample Output
* 5250
* 例: 最高最低等级差不超过1,共4个物品 酋长的女儿 等级3 要求现金10000元 或甲的物品+8000元 或乙的物品+5000元 甲的物品 等级2 要求现金1000元
* 或丙的物品+200元 乙的物品 等级2 要求现金3000元 或丙的物品+200元 丙的物品 等级2 要求现金50元 在这个例子中,
* 最少花费方案是:买丙的东西(50)换乙的东西(+200)换酋长女儿(+5000)一共5250元。
* POJ - 1062
* 每一种购买方式
* 都可以对应虚拟源点到到达终点的一条路径
......
......@@ -6,6 +6,28 @@ import java.util.Scanner;
/**
* https://blog.csdn.net/SWEENEY_HE/article/details/81413683
* H城是一个旅游胜地,每年都有成千上万的人前来观光.为方便游客,巴士公司在各个旅游景点及宾馆、
* 饭店等地都设置了巴士站,并开通了一些单向巴士线路。每条单向巴士线路从某个巴士站出发,
* 依次途径若干个巴士站,最终到达终点巴士站。
* 阿昌最近到H城旅游,住在CUP饭店。他很想去S公园游玩。听人说,
* 从CUP饭店到S公园可能有也可能没有直通巴士。如果没有,就要换乘不同线路的单向巴士,
* 还有可能无法乘巴士到达。现在用整数1,2,...,n给H城的所有巴士站编号,约定CUP饭店的巴士站编号为1,
* S公园巴士站的编号为N。写一个程序,帮助阿昌寻找一个最优乘车方案,使他在从CUP饭店到S公园的过程中换车的次数最少。
* 车站:1 2 3 4 5
* 第一条路线:1 2 3 5
* 第二条路线:1 4
* 第三条路线:4 5
* 则直接选择第一条路线,换车次数最少为0
* 输入
* 第1行是一个数字M(1≤M≤100)表示开通了M条单向巴士线路,第2行是一个数字N(1<N≤500),
* 表示共有N个车站。从第3行到第M+2行依次给出了第一条到第M条巴士线路的信息。
* 其中第i+2行给出的是第i条巴士线路的信息,从左至右依次按行行驶顺序给出了该线路上的所有站点,相邻两个站号之间用一个空格隔开。
* 输出
* 为最少换车次数(在0,1,…,M-1中取值),0表示不需换车即可达到。如果无法乘车达到S公园,则输出"NO"。
* 该题可将一趟公交车经过的站点看成一张图中连通的顶点,且站台之间的距离都为1。
* 每换乘一次会必会使得路径长度加1(因为换乘的目的就是向终点站靠近,
* 所以换乘后的公交到达的最远站点序号必定大于换乘前能到达的最远序号,又由于第一次换乘前至少搭过一个站点(每趟公交至少经过两个站点否则无法换乘),即初始路径为1,所以有:换乘数 = 路径-1;
* 如:样例中 1 - 4的距离为1,2-3,2-4,2-5,3-4,4-5 的距离均为1。第一条公交:1->4,路径 = 1,换乘到第二条公交:4->5,路径 = 2。换乘数 = 路径 - 1 = 1
* 2
* 5
* 1 4
......
......@@ -5,7 +5,33 @@ import java.util.PriorityQueue;
import java.util.Scanner;
/**
*
* 作为城市的紧急救援团队负责人,你将获得一张你所在国家的特殊地图。
* 该地图显示了一些通过道路连接的分散城市,道路是双向的。
* 地图上标出了每个城市的救援队数量以及每对城市之间的每条道路的长度。
* 当其他城市发出紧急求援信息时,你的工作是尽快带领你的士兵前往该地点,同时,在途中尽可能多地调动救援帮手。
* 输入格式
* 第一行包含四个整数 N,表示城市数量(城市编号从 0 到 N−1),M 表示道路数量,C1 表示你当前所在的城市编号,C2 表示发出紧急求援信息的城市编号。
* 第二行包含 N 个整数,其中第 i 个整数表示城市 i 的救援队数量。
* 接下来 M 行,每行包含三个整数 c1,c2,Li,表示城市 c1 和城市 c2 之间存在一条道路相连,道路长度为 Li。
* 数据保证 C1 和 C2 之间至少存在一条路径相连。
* 输出格式
* 共一行,两个整数,第一个整数表示 C1 和 C2 之间最短路的数量,第二个整数表示走最短路的情况下,能聚集到的救援队最大数量。
* 数据范围
* 2≤N≤500,
* 1≤M≤600,
* 1≤Li≤200,
* 每个城市包含的救援人员数量不超过 200。
* 输入样例:
* 5 6 0 2
* 1 2 1 5 3
* 0 1 1
* 0 2 2
* 0 3 1
* 1 2 1
* 2 4 1
* 3 4 1
* 输出样例:
* 2 4
*/
public class 紧急情况 {
public static void main(String[] args) {
......
package graph.单源最短路拓展;
import java.util.Arrays;
import java.util.PriorityQueue;
/**
* https://blog.csdn.net/qq_30277239/article/details/107073569
* “您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。
......@@ -65,5 +68,46 @@ public class 观光 {
}
static int N = 1010, n, m, M;
static int N = 1010, n, m, M = 10005, idx = 1, S, T;
static int[] h = new int[N];
static int[] e = new int[M];
static int[] ne = new int[M];
static int[] w = new int[M];
static int[][] dis = new int[N][2];
static int[][] cnt = new int[N][2];
static boolean[][] st = new boolean[N][2];
static int inf = 0x3f3f3f3f;
static PriorityQueue<node> q = new PriorityQueue<node>();
static int dijkstra() {
Arrays.fill(dis[0], inf);
Arrays.fill(dis[1], inf);
Arrays.fill(cnt[0], 0);
Arrays.fill(cnt[1], 0);
Arrays.fill(st[0], false);
Arrays.fill(st[1], false);
dis[S][0] = 0;
cnt[S][0] = 1;
q.add(new node());
return 1;
}
static void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
static class node implements Comparable<node> {
int dis, type, idx;
@Override
public int compareTo(node node) {
return dis - node.dis;
}
}
}
......@@ -35,6 +35,8 @@ public class 新年好 {
}
/**
* 枚举每个坑里填什么
*
* @param u 当前枚举到第几个
* @param start 当前起点
* @param dist 当前距离
......
......@@ -12,7 +12,7 @@ import java.util.Scanner;
* 对于区间中的某一个点x
* 求出1~N中最少经过几条长度大于x的边,假设最少经过y条,
* (最少经过多少条大于x的边的数量是否小于等于k)
* 把边长大于x的看做1,否则看做0
* 把边长大于x的看做1,否则看做0,非常难
* 用双端队列bfs
*/
public class 通信线路 {
......
......@@ -34,6 +34,7 @@ import java.util.Scanner;
* 3 4 100
* 输出样例:
* 450
* 求出最小生成树,枚举每条非树边,
*/
public class 牛奶运输 {
public static void main(String[] args) {
......@@ -104,11 +105,6 @@ public class 牛奶运输 {
}
}
//求任意两点路径中的单条边权最大值,和次大值
static void work() {
}
/**
* 枚举任意两点路径的最大边权的那条边,由dis[a,b]表示a,b两点路径的最大边权的那条边
*
......@@ -128,6 +124,7 @@ public class 牛奶运输 {
}
/**
* //求任意两点路径中的单条边权最大值,和次大值
* 求任意两点路径中的单条边权最大值,和次大值
*
* @param u 当前节点
......@@ -148,7 +145,7 @@ public class 牛奶运输 {
t2 = t1;
t1 = w[i];
} else if (w[i] > t2 && w[i] != t1) {
//当前边权小于最大值,大于次大值,但不可以与最大值相等,求的是严格次大值
//当前边权小于最大值,大于次大值,但不可以与最大值相等,求的是严格次大值,当然也可以是非严格hh
t2 = w[i];
}
dubbo(j, u, t1, t2, s1, s2);
......
......@@ -7,8 +7,8 @@ import static java.lang.System.in;
/**
* 单点修改,区间查询
* https://www.luogu.com.cn/problemnew/solution/P3368
* tle2个
* https://www.luogu.com.cn/problemnew/solution/P3374
* 已经ac
*/
public class 树状数组 {
......@@ -37,6 +37,7 @@ public class 树状数组 {
public static void main(String[] args) throws IOException {
n = nextInt();
par = new int[n + 1];
m = nextInt();
for (int i = 1; i <= n; i++) {
add(i, nextInt());
......@@ -51,26 +52,22 @@ public class 树状数组 {
} else {
y = nextInt();
z = nextInt();
bw.write(query(y, z ) + "\n");
bw.write(query(y, z) + "\n");
}
}
bw.flush();
}
static int[] par = new int[500005];
static int[] par;
static int n, m;
static void add(int i, int x) {
while (i <= n) {
par[i] += x;
i += lowbit(i);
i += (i & -i);
}
}
private static int lowbit(int i) {
return i & -i;
}
static int query(int l, int r) {
return get(r) - get(l - 1);
}
......@@ -79,7 +76,7 @@ public class 树状数组 {
int res = 0;
while (x != 0) {
res += par[x];
x -= lowbit(x);
x -= (x & -x);
}
return res;
}
......
......@@ -8,7 +8,7 @@ import static java.lang.System.in;
/**
* https://www.luogu.com.cn/problemnew/solution/P3368
* 区间修改,单点查询
* tle1个
* 已经AC
*/
public class 树状数组区间修改 {
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
......@@ -59,23 +59,19 @@ public class 树状数组区间修改 {
}
static int maxn = 500001, n, m;
static long[] tree = new long[maxn];
static long[] a = new long[maxn];
static int[] tree = new int[maxn];
static int[] a = new int[maxn];
//差分数组
static void add(int s, int value) {
for (int i = s; i <= n; i += lowbit(i)) {
for (int i = s; i <= n; i += (i & -i)) {
tree[i] += value;
}
}
static int lowbit(int x) {
return x & -x;
}
static long ask(int s) {
long ans = 0;
for (int i = s; i >= 1; i -= lowbit(i)) {
for (int i = s; i >= 1; i -= (i & -i)) {
ans += tree[i];
}
return ans;
......
......@@ -9,7 +9,7 @@ import java.util.Scanner;
* https://www.acwing.com/solution/acwing/content/1008/
* 巧妙想法,也可以求逆序数!!!
* 建树状数组O(nlogn)
* 天才想法太巧妙啊
* 想法太巧妙啊
*/
public class 楼兰图腾 {
public static void main(String[] args) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册