inlinedoublefx(double x){ return ((a * x + b) * x + c) * x + d; }
inlineintsign(double x){ if (x > 0.01) return1; if (x < -0.01) return-1; return0; }
// 查找区间内一个零点 inlinedoublefind(double left, double right){ int l = sign(fx(left)), r = sign(fx(right)); while (right - left >= 0.01) { double mid = (left + right) / 2; int m = sign(fx(mid)); if (l + m == 0) right = mid; elseif (r + m == 0) left = mid; else return mid; } return left; }
intmain(){ scanf("%lf%lf%lf%lf", &a, &b, &c, &d); // 在 [-100,100] 枚举长度为 1 的区间 int aa = sign(fx(-101)), bb = sign(fx(-100)), i = 0; for (double l = -101; l < 101; l += 1) { if (aa == 0) { ans[i++] = l; if (i == 3) break; } if (aa + bb == 0 && aa - bb != 0) { ans[i++] = find(l, l + 1); if (i == 3) break; } aa = bb; bb = sign(fx(l + 2)); } for (int i = 0; i < 3; ++i) { printf("%.2f ", ans[i]); } return0; }
defcheck(st, jump): """ 给出跳跃距离,返回移除石头数量 """ pre, cnt = 0, 0 for a in st: if a - pre < jump: cnt += 1 else: pre = a return cnt
defmain(): dist, n, m = map(int, input().split()) st = [int(input()) for _ inrange(n)] st.append(dist) left, right = 0, int(2e9) while left < right: mid = (left + right + 1) >> 1 if check(st, mid) <= m: left = mid else: right = mid - 1 print(left) main()
intcheck(int m, int jump){ int pre = 0, cnt = 0; for (int i = 0; i < m; ++i) { if (arr[i] - pre < jump) ++cnt; else pre = arr[i]; } return cnt; }
intmain(){ int dist, n, m; scanf("%d%d%d", &dist, &n, &m); for (int i = 0; i < n; ++i) { scanf("%d", &arr[i]); } arr[n] = dist; int left = 0, right = 2000000000; while (left < right) { int mid = left + ((right - left + 1) >> 1); if (check(n + 1, mid) <= m) left = mid; else right = mid - 1; } printf("%d", left); return0; }
Scannersc=newScanner(System.in); intdist= sc.nextInt(), n = sc.nextInt(), m = sc.nextInt(); int[] st = newint[n + 1]; for (inti=0; i < n; ++i) { st[i] = sc.nextInt(); } st[n] = dist; intleft=0, right = 2000000000; while (left < right) { intmid= left + (right - left + 1 >> 1); if (check(st, mid) <= m) left = mid; else right = mid - 1; } System.out.println(left);
sc.close(); }
publicintcheck(int[] st, int jump) { intpre=0, cnt = 0; for (int a : st) { if (a - pre < jump) ++cnt; else pre = a; } return cnt; } }
defdfs(mat, cur: int, vis: set, i: int, j: int): if mat[i][j] > cur: returnFalse n, m = len(mat), len(mat[0]) if i == n - 1: returnTrue vis.add(xy2int(i, j)) for dx, dy indir: x, y = i + dx, j + dy if x < 0or x >= n or y < 0or y >= m: continue key = xy2int(x, y) if key notin vis and dfs(mat, cur, vis, x, y): returnTrue returnFalse
defmain(): n, m = map(int, input().split()) mat = [list(map(int, input().split())) for _ inrange(n)]
left, right = min(min(a) for a in mat), max(max(a) for a in mat) while left < right: mid = (left + right) >> 1 if check(mat, mid): right = mid else: left = mid + 1 print(left)
const int N = 1007; int mat[N][N], vis[N * N]; int n, m; int dir_x[]{1, 0, 0, -1}, dir_y[]{0, 1, -1, 0};
int xy2int(int x, int y) { return x * N + y; }
bool dfs(int i, int j, int cur) { if (mat[i][j] > cur) return false; if (i == n - 1) return true; vis[xy2int(i, j)] = 1; for (int k = 0; k < 4; ++k) { int dx = dir_x[k], dy = dir_y[k]; int x = i + dx, y = j + dy; if (x < 0 || x >= n || y < 0 || y >= m || mat[x][y] > cur || vis[xy2int(x, y)] == 1) continue; if (dfs(x, y, cur)) return true; } return false; }
int main() { int left = 0, right = N * N, mid; scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &mat[i][j]); right = right < mat[i][j] ? mat[i][j] : right; } } while (left < right) { mid = (left + right) >> 1; if (check(mid)) right = mid; else left = mid + 1; } printf("%d", left); return0; }
constint MAX_VAL = 200007; int n, m, x, y; longlong s; int w[MAX_VAL], v[MAX_VAL], pleft[MAX_VAL], pright[MAX_VAL]; longlong pre_n[MAX_VAL], pre_v[MAX_VAL];
longlongcheck(int pw){ // 计算校验和 longlong ans = 0; // 先预处理出前缀数组; pre_n[0] = 0; pre_v[0] = 0; for (int i = 0; i < n; ++i) { pre_n[i + 1] = pre_n[i] + (w[i] >= pw ? 1 : 0); pre_v[i + 1] = pre_v[i] + (w[i] >= pw ? v[i] : 0); } // 对每个区间计算 for (int i = 0; i < m; ++i) { int l = pleft[i] - 1, r = pright[i] - 1; ans += (pre_n[r + 1] - pre_n[l]) * (pre_v[r + 1] - pre_v[l]); } return ans; }
intmain(){
// redir();
scanf("%d%d%lld", &n, &m, &s); // 读数据 x = 1000007; y = 0; for (int i = 0; i < n; ++i) { scanf("%d%d", &w[i], &v[i]); x = min(x, w[i]); y = max(y, w[i]); } for (int i = 0; i < m; ++i) { scanf("%d%d", &pleft[i], &pright[i]); } // 二分 W longlong y1, y2; int l = x - 1, r = y + 1; // 先查找不小于 s 的最小值 while (l < r) { int mid = (l + r + 1) >> 1; if (check(mid) >= s) l = mid; else r = mid - 1; } y1 = check(l); // 再查找不大于 s 的最大值 for (r = y + 1; l < r; ) { int mid = (l + r) >> 1; if (check(mid) > s) l = mid + 1; else r = mid; } y2 = check(l); printf("%lld\n", min(y1 - s, s - y2)); return0; }
constint N = 1000007; int n, m, r; ll room[N], diff[N], d[N], s[N], t[N];
boolcheck(int day){ memset(diff, 0, sizeof(diff)); for (int i = 0; i < day; ++i) { diff[s[i] - 1] += d[i]; diff[t[i]] -= d[i]; } ll cnt = 0; for (int i = 0; i < n; ++i) { cnt += diff[i]; if (cnt > room[i]) returnfalse; } returntrue; }
intmain(){
scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) { scanf("%lld", &room[i]); } for (int i = 0; i < m; ++i) { scanf("%lld%lld%lld", &d[i], &s[i], &t[i]); } int left = 1, right = m + 1; while (left < right) { int mid = (left + right) >> 1; if (check(mid)) left = mid + 1; else right = mid; } if (left == m + 1) printf("0"); elseprintf("-1\n%d", left); return0; }
P4343 [SHOI2015]自动刷题机
题目背景
曾经发明了信号增幅仪的发明家 SHTSC
又公开了他的新发明:自动刷题机——一种可以自动 AC 题目的神秘装置。
#define ll long long constint N = 100007; int length, k; ll code[N];
intcheck(ll w){ // 计算切题数 int cnt = 0; ll pre = 0; for (int i = 0; i < length; ++i) { pre = max(0ll, pre + code[i]); if (pre >= w) { ++cnt; pre = 0; } } return cnt; }
intmain(){ memset(code, 0, sizeof(code)); scanf("%d%d", &length, &k); // 读入数据同时测测 n 的上界 ll bound = 0, cnt = 0; for (int i = 0; i < length; ++i) { scanf("%lld", &code[i]); cnt = max(0ll, cnt + code[i]); bound = max(cnt, bound); } // 第一次先搜索 n 的最小值 ll left = 1, right = bound; while (left < right) { ll mid = (left + right) >> 1; // 注意 n 越小 k 越大,所以这里要增大 n if (check(mid) > k) left = mid + 1; else right = mid; } if (check(left) != k) { printf("-1"); return0; } printf("%lld", left); // 接下来搜索 n 的最大值 for (right = bound; left < right; ) { ll mid = (left + right + 1) >> 1; if (check(mid) < k) right = mid - 1; else left = mid; } printf(" %lld", left); return0; }