提交 4a5b6647 编写于 作者: qq_36480062's avatar qq_36480062

c

上级 38a788cc
......@@ -59,7 +59,7 @@ public class 八数码 {
// System.out.println(bfs());
}
}
//
// static int bfs(String start) {
// HashMap<String, Integer> dist = new HashMap<String, Integer>();
// HashMap<String, p> prev = new HashMap<String, p>();
......
......@@ -119,7 +119,7 @@ public class 第k短路 {
he[a] = idx++;
}
//处理估价函数
//处理估价函数,从终点往前搜
static void dijkstra() {
PriorityQueue<node> q = new PriorityQueue<node>();
q.add(new node(0, T));
......@@ -147,7 +147,7 @@ public class 第k短路 {
while (!q.isEmpty()) {
tem p = q.poll();
int v = p.t.to, dis = p.t.dis;
if (v == T) {
if (v == T) {//记录出队次数
cnt++;
}
if (cnt == K) return dis;//第k短路
......
......@@ -23,17 +23,17 @@ public class 重复性剪枝 {
static boolean[] vis = new boolean[30];
//当前位置,当前和 w选了多少个
static void dfs(int cnt, int s, int w) {
if (k - w > n - cnt + 1) return;
static void dfs(int u, int s, int w) {
if (k - w > n - u + 1) return;
if (s > sum || w > k) return;
if (cnt == n) {
if (u == n) {
if (s == sum && w == k) {
ans++;
}
return;
}
dfs(cnt + 1, s + a[cnt], w + 1);
dfs(cnt + 1, s, w);
dfs(u + 1, s + a[u], w + 1);
dfs(u + 1, s, w);
}
static void ddf(int s, int cnt, int pos) {
......
......@@ -10,14 +10,22 @@ import static java.lang.System.in;
* 离线
* 预处理O(n)
* 单次查询O(1)
* 5 5 4
* 3 1
* 2 4
* 5 1
* 1 4
* 2 4
* 3 2
* 3 5
* 1 2
* 4 5
* out
* 4
* 4
* 1
* 1
* 2
* 2
* 1
* 4
* 7
* 3
* 4
* 洛谷3379 ac了居然1.23秒也算ac
* 最好的版本!!!
*/
......@@ -46,7 +54,7 @@ public class Tarjan求LCA {
}
public static void main(String[] args) throws IOException {
for (int i = 0; i < parent.length; i++) {
for (int i = 1; i < parent.length; i++) {
parent[i] = i;
}
n = nextInt();
......@@ -102,10 +110,11 @@ public class Tarjan求LCA {
static void tarjan(int u, int fa) {
for (int i = he[u]; i != 0; i = ne[i]) {
if (e[i] != fa) {
tarjan(e[i], u);
union(e[i], u);
vis[e[i]] = true;
int j = e[i];
if (j != fa) {
tarjan(j, u);
union(j, u);
vis[j] = true;
}
}
for (int i = qheadedge[u]; i != 0; i = qnext[i]) {
......
......@@ -73,7 +73,7 @@ public class 倍增LCA {
/**
* 求取每个节点深度
* 和dist[a]存的是a往上直到根节点的权值和
*
* 也可以用bfs
* @param u 当前节点
* @param fa 父节点
* @param d 该节点的深度
......
......@@ -8,6 +8,7 @@ import java.util.StringTokenizer;
import static java.lang.System.in;
/**
* * https://blog.csdn.net/qq_41661919/article/details/86565228
* https://blog.csdn.net/qq_44828887/article/details/107305636
* 给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。
* 设最小生成树的边权之和为sum,
......
......@@ -19,7 +19,7 @@ import static java.lang.System.in;
* 注意欧拉序要开2倍!
* 预处理O(n log n) 在线
* 查询O(1)
* 洛谷3379 re4个..tle3个..
* 洛谷3379 tle3个..超时
*/
public class 欧拉序ST求LCA {
public static void main(String[] args) throws IOException {
......@@ -59,9 +59,9 @@ public class 欧拉序ST求LCA {
return Double.parseDouble(next());
}
static int[] log = new int[25];
static int n, m, len = 0, cnt = 1, root;
static final int maxn = 500005;
static int[] log = new int[maxn];
static int[][] st = new int[maxn << 1][20];
static int[] depth = new int[maxn << 1];//深度
static int[] euler = new int[maxn << 1];//欧拉序
......@@ -82,7 +82,7 @@ public class 欧拉序ST求LCA {
static void init(int root) {
dfs(root, root, 1);
log[1] = 0;
for (int i = 2; i < 25; i++) {
for (int i = 2; i < maxn; i++) {
log[i] = log[i / 2] + 1;
}
for (int i = 1; i <= len; i++) {
......
......@@ -73,7 +73,7 @@ public class 祖孙询问 {
if (depth[up[a][k]] >= depth[b]) {
a = up[a][k];
}
}
}//从高往低跳
if (a == b) return a;
for (int k = 17; k >= 0; k--) {
if (up[a][k] != up[b][k]) {
......@@ -112,10 +112,10 @@ public class 祖孙询问 {
for (int i = h[t]; i != 0; i = ne[i]) {
int j = e[i];
if (depth[j] > depth[t] + 1) {
depth[j] = depth[t] + 1;
depth[j] = depth[t] + 1;//bfs拓展
q.add(j);
up[j][0] = t;
for (int k = 1; k <= 17; k++) {
up[j][0] = t;//记录第一个
for (int k = 1; k <= 17; k++) {//记录后面的up
up[j][k] = up[up[j][k - 1]][k - 1];
}
}
......
......@@ -44,6 +44,12 @@ import java.util.Scanner;
*/
public class 距离Tarjan {
public static void main(String[] args) {
for (int i = 1; i < p.length; i++) {
p[i] = i;
}
for (int i = 0; i < query.length; i++) {
query[i] = new ArrayList<node>();
}
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
......@@ -67,7 +73,7 @@ public class 距离Tarjan {
dfs(1, -1);
tarjan(1);
for (int i = 0; i < m; i++) {
System.out.println(res[i]);
System.out.println(result[i]);
}
}
......@@ -78,11 +84,11 @@ public class 距离Tarjan {
static int[] w = new int[M];
static int[] ne = new int[N];
static int[] st = new int[N];
static int[] res = new int[N];
static int[] result = new int[N];//预处理查询
static int[] p = new int[N];
static int[] dist = new int[N];//记录每个点到根节点的距离
//求每个点到根节点的距离
//求每个点到根节点的距离,前序遍历
static void dfs(int u, int fa) {
for (int i = h[u]; i != 0; i = ne[i]) {
int j = e[i];
......@@ -101,11 +107,12 @@ public class 距离Tarjan {
p[j] = u;
}
}
for (node it : query[u]) {
for (node it : query[u]) {//u->y这条查询,查询编号为2
int y = it.a, id = it.b;
if (st[y] == 2) {
int anc = find(y);
res[id] = dist[u] + dist[y] - dist[anc] * 2;
int anc = find(y);//最近公共祖先
result[id] = dist[u] + dist[y] - dist[anc] * 2;
//u到根节点的距离加上y到根节点的距离减去两个最近共祖先到根节点的距离,就是两点之间的距离
}
}
st[u] = 2;
......@@ -133,13 +140,4 @@ public class 距离Tarjan {
}
static ArrayList<node>[] query = new ArrayList[N];
static {
for (int i = 1; i < p.length; i++) {
p[i] = i;
}
for (int i = 0; i < query.length; i++) {
query[i] = new ArrayList<node>();
}
}
}
......@@ -17,14 +17,14 @@ public class LIS题解 {
static int n;
static int[] arr = new int[100005];
static int[] dp = new int[100005];
static int lis() {
int[] f = new int[100005];
int i = 0, len = 0;
for (int j = 0; j < n; j++) {
i = Arrays.binarySearch(dp, 0, len, arr[j]);
i = Arrays.binarySearch(f, 0, len, arr[j]);
if (i < 0) i = -(i + 1);
dp[i] = arr[j];
f[i] = arr[j];
if (i == len) len++;
}
return len;
......
......@@ -5,19 +5,35 @@ import java.util.Collections;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_41661919/article/details/86565228
* https://blog.csdn.net/qq_44828887/article/details/107305636
* 给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。
* 设最小生成树的边权之和为sum,严格次小生成树就是指边权之和大于sum的生成树中最小的一个。
* https://blog.csdn.net/qq_30277239/article/details/108190012
* 农夫约翰要把他的牛奶运输到各个销售点。
* 运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点。
* 运输的总距离越小,运输的成本也就越低。
* 低成本的运输是农夫约翰所希望的。
* 不过,他并不想让他的竞争对手知道他具体的运输方案,所以他希望采用费用第二小的运输方案而不是最小的。
* 现在请你帮忙找到该运输方案。
* 如果两个方案至少有一条边不同,则我们认为是不同方案;
* 费用第二小的方案在数值上一定要严格小于费用最小的方案;
* 答案保证一定有解;
* 输入格式
* 第一行包含两个整数N和M。
* 接下来M行,每行包含三个整数x,y,z,表示点x和点y之前存在一条边,边的权值为z。
* 第一行是两个整数 N,M,表示销售点数和交通线路数;
* 接下来 M 行每行 3 个整数 x,y,z,表示销售点 x 和销售点 y 之间存在线路,长度为 z。
* 输出格式
* 包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
* 输出费用第二小的运输方案的运输总距离。
* 数据范围
* N≤105,M≤3∗105
* 思路
* lca次小生成树。倍增找树上路径最大边即可。
* 1≤N≤500,
* 1≤M≤10^4,
* 1≤z≤10^9,
* 数据中可能包含重边。
* 输入样例:
* 输入样例:
* 4 4
* 1 2 100
* 2 4 200
* 2 3 250
* 3 4 100
* 输出样例:
* 450
*/
public class 牛奶运输 {
public static void main(String[] args) {
......@@ -53,7 +69,7 @@ public class 牛奶运输 {
}
long res = (long) 1e18;
for (int i = 0; i < m; i++) {
if (!edge.get(i).isShu) {
if (!edge.get(i).isShu) {//遍历非树边
a = edge.get(i).a;
b = edge.get(i).b;
w = edge.get(i).w;
......@@ -65,6 +81,14 @@ public class 牛奶运输 {
System.out.println(res);
}
/**
* 枚举任意两点路径的最大边权的那条边,由dis[a,b]表示a,b两点路径的最大边权的那条边
*
* @param u 当前点
* @param fa 父节点
* @param maxd 最大边权
* @param d 结果记录
*/
static void dfs(int u, int fa, int maxd, int[] d) {
d[u] = maxd;
for (int i = h[u]; i != 0; i = ne[i]) {
......@@ -75,6 +99,36 @@ public class 牛奶运输 {
}
}
/**
* 求任意两点路径中的单条边权最大值,和次大值
*
* @param u 当前节点
* @param fa 父节点,从哪来的
* @param r1 最大值
* @param r2 次大值
* @param s1 记录最大值
* @param s2 记录次大值
*/
static void dubbo(int u, int fa, int r1, int r2, int[] s1, int[] s2) {
s1[u] = r1;
s2[u] = r2;
for (int i = h[u]; i != 0; i = ne[i]) {
int j = e[i];
if (j != fa) {
int t1 = r1, t2 = r2;//结合当前边的边权修改最大值,最小值
if (w[i] > t1) {//当前边权比最大值还大
t2 = t1;
t1 = w[i];
} else if (w[i] > t2 && w[i] != t1) {
//当前边权小于最大值,大于次大值,但不可以与最大值相等,求的是严格次大值
t2 = w[i];
}
dubbo(j, u, t1, t2, s1, s2);
}
}
}
static void add(int a, int b, int c) {
e[cnt] = b;
w[cnt] = c;
......@@ -106,9 +160,11 @@ public class 牛奶运输 {
static int n, m, N = 510, cnt = 1, M = 10010;
static ArrayList<node> edge = new ArrayList<node>();
static int[] p = new int[N];//并查集
static int[][] dis = new int[N][N];
static int[][] dis = new int[N][N];//两点路径中单条边权最大值,参见dfs
static int[] h = new int[N];
static int[] e = new int[M];
static int[] w = new int[M];
static int[] ne = new int[M];
static int[][] m1 = new int[N][N];//两点路径中单条边权最大值,用dubbo方法求解
static int[][] m2 = new int[N][N];//两点路径中单条边权次大值
}
......@@ -38,7 +38,7 @@ public class 走廊泼水节 {
res += (size[a] * size[b] - 1) * (c.w + 1);//新边都取w+1
System.out.println(Arrays.toString(size));
size[b] += size[a];//合并两个集合
par[a] = b;
par[a] = b;//a指向b
}
}
System.out.println(res);
......
......@@ -34,7 +34,8 @@ public class 快速乘 {
System.out.println(ks(a, b, p));
System.out.println(ca(2, 20));
}
//递归快速乘
//递归快速乘转化为加法
static int ca(int a, int b) {
int res = 0;
if (b == 0) return res;
......
......@@ -5,12 +5,12 @@ import java.util.Scanner;
/**
* https://www.acwing.com/solution/acwing/content/12579/
* https://www.hzxueyan.com/archives/85/
* 监狱有连续编号为 11 到 nn 的 nn 个房间,每个房间关押一个犯人。
* 有 mm 种宗教,每个犯人可能信仰其中一种。
* 监狱有连续编号为 1 到 n 的 n 个房间,每个房间关押一个犯人。
* 有 m种宗教,每个犯人可能信仰其中一种。
* 如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。
* 求有多少种状态可能发生越狱。
* 输入
* 共一行,包含两个整数 mm 和 nn。
* 共一行,包含两个整数 mn。
* 输出
* 可能越狱的状态数,对 100003取余。
* 数据范围
......@@ -19,7 +19,7 @@ import java.util.Scanner;
* 输出样例
* 6
* 样例解释
* 所有可能的 66 种状态为:(000)(001)(011)(100)(110)(111)(000)(001)(011)(100)(110)(111)。
* 所有可能的 6 种状态为:(000)(001)(011)(100)(110)(111)
*/
public class 越狱 {
public static void main(String[] args) {
......
......@@ -17,7 +17,6 @@ public class 楼兰图腾 {
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
// max_value = Math.max(a[i], max_value);//记录数组最大值
}
/**
* 正序循环,巧妙想法,也可以求逆序数
......
package 线段树;
import java.io.*;
import java.util.StringTokenizer;
import static java.lang.System.in;
public class seg {
public static void main(String[] args) throws IOException {
n = nextInt();
m = nextInt();
build(1, 1, n);
int l, r, d;
while (m-- != 0) {
if (next().charAt(0) == 'C') {
l = nextInt();
r = nextInt();
d = nextInt();
update(1, l, r, d);
} else {
l = nextInt();
r = nextInt();
bw.write(query(1, l, r) + "\n");
}
}
bw.flush();
}
static class node {
int l, r;
long sum;//区间和
int lazy;//懒标记,给当前节点为根的子树中的每一个节点加上lazy(设计不包含根节点)
//只要递归到子区间就pushdown
public node(int l, int r, int sum) {
this.l = l;
this.r = r;
this.sum = sum;
}
}
static void build(int k, int l, int r) throws IOException {
if (l == r) {
tr[k] = new node(l, r, nextInt());
} else {
tr[k] = new node(l, r, 0);
int mid = l + r >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
pushup(k);
}
}
private static void pushup(int k) {
tr[k].sum = tr[k << 1].sum + tr[k << 1 | 1].sum;
}
static void update(int k, int l, int r, int d) {
if (tr[k].l >= l && tr[k].r <= r) {
tr[k].sum += (tr[k].r - tr[k].l + 1) * d;
tr[k].lazy += d;
return;
}
down(k);
int mid = tr[k].l + tr[k].r >> 1;
if (l <= mid) update(k << 1, l, r, d);
if (r > mid) update(k << 1 | 1, l, r, d);
pushup(k);
}
static long query(int k, int l, int r) {
if (tr[k].l >= l && tr[k].r <= r) {
return tr[k].sum;
}
down(k);
int mid = tr[k].l + tr[k].r >> 1;
long ans = 0;
if (l <= mid) ans += query(k << 1, l, r);
if (r > mid) ans += query(k << 1 | 1, l, r);
return ans;
}
private static void down(int k) {
if (tr[k].lazy != 0) {
tr[k << 1].sum += (tr[k << 1].r - tr[k << 1].l + 1) * tr[k].lazy;
tr[k << 1 | 1].sum += (tr[k << 1 | 1].r - tr[k << 1 | 1].l + 1) * tr[k].lazy;
tr[k << 1].lazy += tr[k].lazy;
tr[k << 1 | 1].lazy += tr[k].lazy;
tr[k].lazy = 0;
}
}
static int N = (int) (1e5 + 2), n, m;
static node[] tr = new node[N * 4];
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException {// 读取下一行字符串
return reader.readLine();
}
static String next() throws IOException {// 读取下一个字符串
while (!tokenizer.hasMoreTokens()) {
//如果没有字符了,就是下一个,使用空格拆分,
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {// 读取下一个int型数值
return Integer.parseInt(next());
}
static double nextDouble() throws IOException {// 读取下一个double型数值
return Double.parseDouble(next());
}
}
......@@ -40,7 +40,7 @@ public class m任取n满足 {
static void f(int u, int sum, int s) {
if (sum + n - u < k) return;//n-u是剩余可选的数,
if (sum > k) return;
if (u == n) {
if (u == n) {//枚举到最后一个元素
if (sum == k && s == suma)
ans++;
return;
......@@ -50,6 +50,7 @@ public class m任取n满足 {
f(u + 1, sum + 1, s + arr[u]);
}
static boolean[] x = new boolean[30];
/**
......
package 递归;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import static java.lang.System.in;
......@@ -35,7 +36,7 @@ public class 排列枚举 {
Scanner sc = new Scanner(in);
n = sc.nextInt();
long s = System.nanoTime();
d(0, 0);
d( 0);
long t = System.nanoTime();
System.out.println((t - s) / 1e8);
s = System.nanoTime();
......@@ -66,17 +67,17 @@ public class 排列枚举 {
}
}
static int[] arr = {4, 3, 5, 2, 3, 4, 1, 4, 5, 1, 2};
static int[] arr = {1, 2, 3, 4, 5, 4, 1, 4, 5, 1, 2};
//最快
static void d(int u, int k) {
if (u == n) {
// System.out.println(Arrays.toString(arr));
static void d( int k) {
if (k== n) {
System.out.println(Arrays.toString(arr));
return;
}
for (int i = k; i < n; i++) {
swap(i, k);
d(u + 1, k + 1);
d( k + 1);
swap(i, k);
}
}
......
......@@ -4,7 +4,8 @@ import java.util.Scanner;
/**
* https://blog.csdn.net/qq_38735931/article/details/89395313#A%20%E5%AE%B6%E8%B0%B1%C2%A0
* 这一天蒜头君拿到了自己家的家谱,蒜头君便想知道,在自己家的家谱中,每位祖先有多少直系后代(直系后代包括他的孩子和他孩子的直系后代)。但是家族历史源远流长,家谱实在太庞大了,自己一个人完全数不过来。热心的你便自告奋勇帮蒜头君写一个程序,来统计每位祖先有多少直系后代。
* 这一天蒜头君拿到了自己家的家谱,蒜头君便想知道,在自己家的家谱中,每位祖先有多少直系后代(直系后代包括他的孩子和他孩子的直系后代)。
* 但是家族历史源远流长,家谱实在太庞大了,自己一个人完全数不过来。热心的你便自告奋勇帮蒜头君写一个程序,来统计每位祖先有多少直系后代。
* 输入格式
* 输入的第一行有一个整数 n(1≤n≤100000),表示家谱中的总人数。
* 接下来读入 n−1行,每行有两个整数 x(1≤x≤n), y(1≤y≤n),表示 x 是 y 的父母。
......
......@@ -25,14 +25,30 @@ package 递归;
*/
public class 随机选数 {
public static void main(String[] args) {
// Scanner sc = new Scanner(in);
// n = sc.nextInt();
dfs(0, 0);
// long l = System.nanoTime();
// f(0);
// long r = System.nanoTime();
// System.out.println((r - l) / 1e8);
// l = System.nanoTime();
//dfs(0, 0);
for (int i = 0; i < 1 << n; i++) {
for (int j = 0; j < n; j++) {
if ((i >> j & 1) == 1)
System.out.print(j + 1 + " ");
}
System.out.println();
}
//位运算求子集
// r = System.nanoTime();
// System.out.println((r - l) / 1e8);
}
static int n = 3;
static int[] arr = {1, 2, 3};
static int n = 4;
static int[] arr = {1, 2, 3, 4, 5, 6};
static int[] vis = new int[10];
//dfs求子集,选和不选
......@@ -54,9 +70,25 @@ public class 随机选数 {
vis[u] = 0;
}
static boolean[] st = new boolean[23];
static void f(int u) {
if (u == n) {
for (int i = 0; i < n; i++) {
if (st[i]) System.out.print(arr[i] + " ");
}
System.out.println();
return;
}
f(u + 1);
st[u] = true;
f(u + 1);
st[u] = false;
}
static void dfs(int u, int state) {
if (u == n) {
if (state==0)return;
if (state == 0) return;
for (int i = 0; i < n; i++) {
if (((state >> i) & 1) == 1)
System.out.print(arr[i] + " ");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册