1. 区间合并
输入
5
5 6
1 4
10 10
6 9
8 10
输出
1 4
5 10
💖 Main.java
import java.util.Arrays;
import java.util.Scanner;
public class Main
{
static int N = 100010;
static int n;
// 区间类
static class Node
{
int l;// 区间左端点
int r;// 区间右端点
public Node(int l, int r)
{
this.l = l;
this.r = r;
}
}
public static void main(String[] args)
{
// 输入区间数据
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
Node[] range = new Node[n];
for (int i = 0; i < n; i++)
{
int l = sc.nextInt();
int r = sc.nextInt();
range[i] = new Node(l, r);
}
// 数组按 区间左端点进行排序
Arrays.sort(range, (o1, o2) -> o1.l - o2.l);
// 连续被覆盖的大区间 [left,right]
int left = range[0].l;
int right = range[0].r;
for (int i = 1; i < n; i++)
{
// 当前区间的左边界 <= 前一个连续大区间:两区间能衔接起来
if (range[i].l <= right)
{
right = range[i].r;
} else // 两区间衔接不上了
{
System.out.println(left + " " + right);// 输出前一个大区间
// 更新大区间的边界
left = range[i].l;
right = range[i].r;
}
}
System.out.println(left + " " + right);// 输出最后一个大区间
}
}
2. 模拟退火(SA)
💖 Cpp
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8; // 终止温度
double y;
double func(double x) // 计算函数值
{
return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}
double solve(void)
{
double T = 100; // 初始温度
double delta = 0.98; // 降温系数
double x = 50.0; // x的初始值
double now = func(x); // 计算初始函数值
double ans = now; // 返回值
while (T > eps) {
int f[2] = {1, -1};
double newx = x + f[rand() % 2] * T; // 按概率改变x,随t的降温而减少
if (newx >= 0 && newx <= 100) {
double next = func(newx);
ans = min(ans, next);
if (now - next > eps) {
x = newx;
now = next;
}
}
T *= delta;
}
return ans;
}
int main(void)
{
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%lf", &y);
printf("%.4lf\n", solve());
}
return 0;
}
3. 谁在中间
💖 Main.java
import java.util.Arrays;
import java.util.Scanner;
public class Main
{
static int N = (int) 1e5 + 10;
static int[] a = new int[N];
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
// 输入
int T = sc.nextInt();
while (T-- > 0)
{
int n = sc.nextInt();
for (int i = 0; i < n; i++)
a[i] = sc.nextInt();
Arrays.sort(a, 0, n);// 排序
System.out.println(a[n >> 1]);// 取中间值
}
}
}
输入
1
5 1 2 4 5 3
输出
3
4. 求逆序对
💖 Main.java
归并求逆序对
import java.util.Scanner;
public class Main
{
static int N = 100010;
static int[] q = new int[N], tmp = new int[N];
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
for (int i = 0; i < n; i++)
q[i] = sc.nextInt();
long cnt = mergeSort(0, n - 1);
System.out.println(Math.max(0, cnt - k));
}
/**
* @param l 区间左边界
* @param r 区间右边界
* @return long 类型的区间内的逆序对
*/
private static long mergeSort(int l, int r)
{
// 递归出口
if (l >= r)
return 0;// 区间只有一个数了,没有逆序队
// 分
int mid = l + r >> 1;
long res = mergeSort(l, mid) + mergeSort(mid + 1, r);
// 治 (归并)
int k = 0;// 临时数组指针
int i = l;// 左区间指针
int j = mid + 1;// 右区间指针
while (i <= mid && j <= r)
{
if (q[i] <= q[j])// 无逆序对
tmp[k++] = q[i++];
else
{// 右边区间的数比左边区间的数小,有逆序对
tmp[k++] = q[j++];
res += mid - i + 1;
}
}
// 断后
if (i <= mid)
tmp[k++] = q[i++];
if (j <= r)
tmp[k++] = q[j++];
// 物归原主
for (i = l, j = 0; i <= r; i++, j++)
{
q[i] = tmp[j];
}
return res;
}
}
输入
3 1
2 2 1
输出
1