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

commit

上级 1ab76bf1
package basic.UnionFind;
import java.util.Scanner;
/**
* 带权并查集
* 精髓:只要两个元素在一个集合里面,
* 通过它们与根节点的距离就能知道它们的相对关系
*/
public class 食物链 {
static int[] p = new int[100005], dir = new int[1000005];
static int find(int x) {
if (p[x] != x) {
int t = find(p[x]);
//t代表最祖先节点
dir[x] += dir[p[x]];
//记录p[x]这个节点到祖先的距离
p[x] = t;
}
return p[x];
}
static int n, m;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= n; i++) {
p[i] = i;
}
int res = 0;
int t, x, y;
while (m-- != 0) {
t = sc.nextInt();
x = sc.nextInt();
y = sc.nextInt();
//如果没有这种动物,肯定就是假话
if (x > n || y > n) res++;
else {
int px = find(x), py = find(y);
if (t == 1) {
if (px == py && (dir[x] - dir[y]) % 3 != 0) res++;
else {
p[px] = py;
dir[px] = dir[y] - dir[x];
}
} else {
if (px == py && (dir[x] - dir[y] - 1) % 3 != 0) res++;
else if (px != py) {
p[px] = py;
dir[px] = dir[y] + 1 - dir[x];
}
}
}
}
System.out.println(res);
}
}
package basic.queue;
/**
* https://www.acwing.com/problem/content/156/
* 给定一个大小为n≤106
* 的数组。
* 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。
* 您只能在窗口中看到k个数字。
* 每次滑动窗口向右移动一个位置。
* 以下是一个例子:
* 该数组为[1 3 -1 -3 5 3 6 7],k为3。
* 窗口位置 最小值 最大值
* [1 3 -1] -3 5 3 6 7 -1 3
* 1 [3 -1 -3] 5 3 6 7 -3 3
* 1 3 [-1 -3 5] 3 6 7 -3 5
* 1 3 -1 [-3 5 3] 6 7 -3 5
* 1 3 -1 -3 [5 3 6] 7 3 6
* 1 3 -1 -3 5 [3 6 7] 3 7
* 您的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。
* 输入格式
* 输入包含两行。
* 第一行包含两个整数n和k,分别代表数组长度和滑动窗口的长度。
* 第二行有n个整数,代表数组的具体数值。
* 同行数据之间用空格隔开。
* 输出格式
* 输出包含两个。
* 第一行输出,从左至右,每个位置滑动窗口中的最小值。
* 第二行输出,从左至右,每个位置滑动窗口中的最大值。
* 输入样例:
* 8 3
* 1 3 -1 -3 5 3 6 7
* 输出样例:
* -1 -3 -3 -3 3 3
* 3 3 5 5 6 7
* 这道题目,我们就维护两个队列,一个是最小值,一个是最大值.
* 这里唯一的重点就是,每一次入队的时候,不需要管是不是比队头小,
* 因为也许他现在小,但是在队头出队列后,他还在,而且是最小的值.
* 然后我们可以发现一个性质:
* 如果队列中存在两个元素,满足 a[i] >= a[j] 且 i < j,
* 那么无论在什么时候我们都不会取 a[i] 作为最小值了,
* 所以可以直接将 a[i] 删掉;
* 也就是下标小,存的值大,不选,因为起码都有2个
*/
public class 单调队列 {
public static void main(String[] args) {
......
......@@ -16,6 +16,15 @@ import static java.lang.System.in;
* 这样就可以O(1)实现对数组进行区间加减
* 构造也是上述构造!!!
* 不考虑前置构造,直接更新!!!
* 第二种构造方法:如上找到规律
* b[4]=a[4]-a[3]
* b[3]=a[3]-a[2]
* b[2]=a[2]-a[1]
* b[1]=a[1]-a[0]
* 所以可以倒序从n~1
* b[i]=a[i]-a[i-1]
* 这样构造,也可以
* 给出证明:a[i]=b[i]+b[i-1]+...+b[1]=a[i]-a[i-1]+a[i-1]-a[i-2]+...+a[1]=a[i]
*/
public class 差分 {
public static void main(String[] args) throws IOException {
......
package 前缀和差分;
import java.util.Scanner;
/**
*
* 给定一个n*m的大矩阵,在里面求得一个c*c的矩阵
*/
public class 激光炸弹 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
r = sc.nextInt();
int x, y, w;
while (n-- != 0) {
x = sc.nextInt();
y = sc.nextInt();
w = sc.nextInt();
a[++x][++y] += w;
}
for (int i = 1; i <= 5000; i++) {
for (int j = 1; j <= 5000; j++) {
qzh[i][j] += qzh[i - 1][j] + qzh[i][j - 1] - qzh[i - 1][j - 1] + a[i][j];
}
}
long res = 0;
for (int i = 1; i <= 5000 - r + 1; i++) {
for (int j = 1; j <= 5000 - r + 1; j++) {
res = Math.max(get(i, j, i + r - 1, j + r - 1), res);
}
}
System.out.println(res);
}
static int n, r;
static int[][] qzh = new int[5005][5005];
static int[][] a = new int[5005][5005];
static int get(int x1, int y1, int x2, int y2) {
return qzh[x2][y2] - qzh[x1 - 1][y2] - qzh[x2][y1 - 1] + qzh[x1 - 1][y1 - 1];
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册