2011 noip 提高组
首先吐槽:刚刚写着写着突然蓝屏了,,emmm,写到最后一题了蓝屏了、
当时我的内心是崩溃的。
然后,旁边的大佬默默来了一句:论保存草稿的重要性。
连着蓝了三次之后开了防火墙,然后,,我左边那位同学又开始蓝屏了。。
Day 1
T1 铺地毯
判断条件是
x >= a[i] &&x <= a[i] + g[i] && y >= b[i] && y <= b[i] + k[i]
#include <cstdio> int n, a[10000], b[10000], g[10000], k[10000], t, x, y; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d%d%d%d", &a[i], &b[i], &g[i], &k[i]); scanf("%d%d", &x, &y); for(int i = 1; i <= n; i++) if(x >= a[i] &&x <= a[i] + g[i] && y >= b[i] && y <= b[i] + k[i]) t = i; t == 0 ? printf("-1") : printf("%d", t); return 0; }
T2 选择客栈
把三重循环的暴力优化成一层。
#include <cstdio> #include <iostream> #define in inline #define is isdigit using namespace std; in int read() { int X = 0, w = 0; char ch = 0; while(!is(ch)) { w |= ch == '-'; ch = getchar(); } while(is(ch)) { X = (X << 3) + (X << 1) + (ch ^ 48); ch = getchar(); } return w ? -X : X; } void print(int x) { if(x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0'); } int n, k, p, m, sum, num, ans, a[20010], b[20010], c[20000]; int main() { n = read(); k = read(); p = read(); for(int i = 1; i <= n; i++) { num = read(); sum = read(); if(sum <= p) m = i; if(m >= a[num]) c[num] = b[num]; a[num] = i; ans += c[num]; b[num]++; } print(ans); return 0; }
T3 Mayan游戏
大模拟搜索题,唔,,,我的代码会被hack,,虽然A了。
这里参照一位大佬的做法->https://www.luogu.org/blog/sumijie/solution-p1312
Day 2
T1 计算系数
大家都用杨辉三角但是我太弱了,,不会
于是,dp
#include <cstdio> long long f[1005][1005] = {1}, a, b, n, m, k; int main() { scanf("%lld%lld%lld%lld%lld", &a, &b, &k, &n, &m); for(int i = 0; i <= n; i++) for(int j = 0; j <= m; j++) { if(i) f[i][j] = (f[i][j] + f[i - 1][j] * a) % 10007; if(j) f[i][j] = (f[i][j] + f[i][j - 1] * b) % 10007; } printf("%lld", f[n][m]); return 0; }
T2 聪明的质检员
非常经典的二分题目,出去学习老师们应该都会讲
#include <cmath> #include <cstdio> #include <algorithm> using namespace std; int w[200001], v[200001], l[200001], r[200001], m, n, ll, rr = 1000000; long long sumw[200001], sumv[200001], s, ansn = 10000000000000000LL; long long ok(int mid) { long long ret = 0; for(int i = 1; i <= n; ++i) if(w[i] >= mid) sumw[i] = sumw[i - 1] + 1, sumv[i] = sumv[i - 1] + v[i]; else sumw[i] = sumw[i - 1], sumv[i] = sumv[i - 1]; for(int i = 1; i <= m; ++i) ret += (sumw[r[i]] - sumw[l[i] - 1]) * (sumv[r[i]] - sumv[l[i] - 1]); return ret; } int main() { scanf("%d%d%lld", &n, &m, &s); for(int i = 1; i <= n; ++i) scanf("%d%d", &w[i], &v[i]); for(int i = 1; i <= m; ++i) scanf("%d%d", &l[i], &r[i]); while(ll < rr) { int mid = (ll + rr) / 2 + 1; long long tmp = ok(mid) - s; ansn = min(ansn, abs(tmp)); if(tmp > 0) ll = mid; else if(tmp < 0) rr = mid - 1; else { ansn = 0; break; } } printf("%lld", ansn); }
T3 观光公交
贪心的经典题目
#include <cstdio> #include <iostream> using namespace std; #define MAXN 10100 int p, temp, ans, n, m, k, d[MAXN], t[MAXN], a[MAXN], b[MAXN], num[MAXN], vis[MAXN], dis[MAXN], sum[MAXN]; int main() { scanf("%d%d%d", &n, &m, &k); for(int i = 1; i < n; i++) scanf("%d", &d[i]); for(int i = 1; i <= m; i++) scanf("%d%d%d", &t[i], &a[i], &b[i]); for(int i = 1; i <= m; i++) num[b[i]]++, vis[a[i]] = max(vis[a[i]], t[i]); for(int i = 2; i <= n; i++) dis[i] = max(dis[i - 1], vis[i - 1]) + d[i - 1]; for(int i = 1; i <= m; i++) ans += dis[b[i]] - t[i]; while(k--) { p = temp = -1; for(int i = n - 1; i; i--) { dis[i + 1] <= vis[i + 1] ? sum[i] = num[i + 1] : sum[i] = sum[i + 1] + num[i + 1]; if(sum[i] > temp && d[i]) temp = sum[i], p = i; } if(p == -1) break; ans -= temp, d[p]--; for(int i = p + 1; i <= n; i++) dis[i] = max(dis[i - 1], vis[i - 1]) + d[i - 1]; } printf("%d", ans); return 0; }