二分
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int T, n;
struct node {
int s, e, d;
} ;
node a[N];
int f(int x) {
int res = 0;
for (int i = 1; i <= n; i++)
if (x >= a[i].s)
res += (min(a[i].e, x) - a[i].s) / a[i].d + 1;
return res;
}
main() {
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i].s >> a[i].e >> a[i].d;
int l = 0, r = 2147483647;
while (l < r) {
int mid = l + r >> 1;
if (f(mid) % 2 == 1)
r = mid;
else
l = mid + 1;
}
int sum = f(l) - f(l - 1);
if (sum % 2 == 1)
cout << l << " "<<sum << '\n';
else
puts("There's no weakness.");
}
return 0;
}
路标设置
最大值最小
// 空旷指数
bool check(int x) {
int last = a[1];
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (a[i] - last > x) {
cnt++;
last = last + x;
i--; // 接下来还要在判断一次 a[i] 和 last
} else
last = a[i];
}
return cnt <= k;
}
// 跳石头
// 最小值最大
// 判断在给定的距离x下,
// 移走的是否数量能否小于等于 m
bool check(int x) {
int last = 0, cnt = 0;
for (int i = 1; i <= n; i++) {
if (a[i] - last < x)
cnt++;
else
last = a[i];
}
// 到终点也特判
if(end - last < x) cnt++;
return cnt<=m;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m, a[N], tmp;
long long res;
int main() {
cin >> m >> n;
for (int i = 1; i <= m; i++)
cin >> a[i];
sort(a + 1, a + 1 + m);
for (int i = 1; i <= n; i++) {
cin >> tmp;
int t = lower_bound(a + 1, a + 1 + m, tmp) - a;
if (t == 1)
res += a[1] - tmp;
else if (t == m + 1)
res += tmp - a[m];
else res += min(abs(a[t] - tmp), abs(tmp - a[t - 1]));
}
cout << res;
return 0;
}
//x1<x2 , 且 f(x1)*f(x2)<=0
//意味着在 x1 和 x2 之间存在一个根
//
//mid = (l+r)/2;
//f(x1)*f(mid)<=0 根在 x1 - mid 之间
//否则 根在 mid 到 x2 之间
// 根的范围在 -100 到 100 之间
// 根与根的绝对值大于等于 1
#include <bits/stdc++.h>
using namespace std;
double a, b, c, d;
double eps = 1e-3;
// 一元三次函数
double f(double x) {
return a * x * x * x + b * x * x + c * x + d;
}
int main() {
cin >> a >> b >> c >> d;
for (double i = -100 ; i < 100 ; i++) {
// 判断 l - r 之间有没有根
double l = i, r = i + 1;
if (f(l) == 0) {
printf("%.2lf ", l);
}
if (f(l)*f(r) < 0) { // 存在 根
// 实数二分
while (l + eps <= r) {
double mid = (l + r) / 2;
if (f(l)*f(mid) <= 0)
r = mid;
else
l = mid;
}
printf("%.2lf ", l);
}
}
return 0;
}
进击的奶牛
模板,最小值最大
// 在距离为 x 的情况能放置几头牛
bool check(int x) {
int cnt=1, last = a[1];
for(int i=2;i<=n;i++)
if(a[i] - last>=x)
last = a[i] , cnt++;
return cnt>=m;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a[N];
int ans;
// 实现check 函数
// 在每段和的最大值为 x 的情况下,是否能凑出 不超过 M 段
bool check(int x) { // 数列分段I
int sum = 1, last = a[1];
for (int i = 2; i <= n; i++) {
if (last + a[i] <= x)
last += a[i];
else
last = a[i], sum++;
}
return sum <= m;
}
int main() {
scanf("%d%d", &n, &m);
int l = 0, r = 1e9;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
l = max(l, a[i]);
}
// 最大值最小
while (l < r) {
int mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
cout << l;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int a[N];
int ans;
// 实现 check 函数
bool check(int x) {
long long sum = 0;
// 统计在 锯片高度 x 下能得到的木材的长度
for (int i = 1; i <= n; i++)
if (a[i] > x)
sum += a[i] - x;
return sum >= m * 1LL;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int l = 0, r = 1e9;
// 最小值最大
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
cout << l;
return 0;
}
//a - b = c
//等价于 a = b+c
//枚举 b , 得到 b 的值
//算出来 a = b+c ,
//只需要统计 有几个 a 就行了
//排序, 二分查找 a 的个数
//upper_bound - lower_bound
#include <bits/stdc++.h>
using namespace std;
long long n, a[100000000], c, ans;
int main() {
cin >> n >> c;
for (int i = 1; i <= n; i++)
cin >> a[i];
// 二分, 有序
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
// b 的值是 a[i]
// a 的 值是 a[i] + c
// 找 a 的个数
ans += upper_bound(a + 1, a + 1 + n, a[i] + c) - lower_bound(a + 1, a + n + 1, a[i] + c);
cout << ans;
return 0;
}
//两个函数
//查找到第一个 大于等于 查找的值的 位置
//lower_bound(查找的起始位置,查找的结束位置,查找的值)
//
//查找到第一个 大于 查找的值的 位置
//upper_bound(查找的起始位置,查找的结束位置,查找的值)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int a[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
while (m--) {
int tmp;
scanf("%d", &tmp);
// 数组的起始位置,就是数组名
int t = lower_bound(a + 1, a + 1 + n, tmp) - a;
if (a[t] == tmp)
printf("%d ", t);
else
printf("%d ", -1);
}
return 0;
}
最大值最小模板
while (l < r) {
int mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
最小值最大 模板
while (l < r) {
int mid = l + r + 1 >> 1;
if ( check(mid) )
l = mid;
else
r = mid - 1;
}
// 单调不减:a[i]<=a[i+1]
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int a[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
while (m--) {
int tmp;
scanf("%d", &tmp);
// 查询第一个大于等于 tmp 的位置
// l r mid 都是下标
int l = 1, r = n;
// 最大值最小
while (l < r) { // 当循环条件退出的时候,一定是满足 l == r 的
int mid = l + r >> 1;
if (a[mid] >= tmp)
r = mid;
else
l = mid + 1;
}
// 要的是刚好相等
if (a[l] == tmp)
printf("%d ", l);
else
printf("%d ", -1);
}
return 0;
}