对于某唤做赛区难度的题,我只能是内流满面。。拿到题,A神题不可做,B,神题不可做,C,神题不可做。。。最后yy了一个A的算法。。。只得了20 TAT。C题骗分似乎有50 。。B题本来想骗分。。然后/ 写成 % 了。。 听说/ 可得80 。。
算了写题解吧。。 A暂时不会。。早上听了再写
B:
这个题得写法太过于机智了。。三种a, b, ans, 将ans 和 a 作为i, j。。何不奇葩。。首先需要明白对于a选b中的元素,选后面的不如取前面的,每转移一次看是否能对答案进行更新,然后在看是否能够转移,应为ai与bi的相等的位置是呈单调递增的,所以对与一个ai,找到一个比当前已经匹配了的点后最近的一个与ai想对应的进行转移。但是二分的时候要特判一下会不会这个对应为空或一定不合法。。。。我re 90了30分钟就是这个地方。。还有while的判断不要再写抽了。。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 102000; const int maxv = 310; const int inf = 0x3f3f3f3f; int n, m, s, e; int a[maxn], b[maxn]; vector <int> pos[maxn]; int f[maxn][maxv]; int smax = 0; void read() { scanf("%d%d%d%d", &n, &m, &s, &e); for(int i = 1; i <= n; ++ i) { scanf("%d", &a[i]); } smax = s / e + 1; for(int i = 1; i <= m; ++ i) { scanf("%d", &b[i]); pos[b[i]].push_back(i); } a[0] = b[0] = -1; } int ans = 0; void sov() { memset(f, inf, sizeof(f)); f[0][0] = 0; for(int i = 1; i <= n; ++ i) { f[i][0] = 0; for(int j = 1; j <= smax; ++ j) { f[i][j] = f[i - 1][j]; int ls = -1; int rs = pos[a[i]].size() - 1; if(rs < 0 || pos[a[i]][rs] <= f[i - 1][j - 1]) continue; while(rs - ls > 1) { int mid = (ls + rs) >> 1; if(pos[a[i]][mid] > f[i - 1][j - 1]) rs = mid; else ls = mid; } if(rs < pos[a[i]].size()) f[i][j] = min(f[i][j], pos[a[i]][rs]); if(e * j + i + f[i][j] <= s) ans = max(ans, j); } } printf("%d\n", ans); } int main() { read(); sov(); return 0; }
C: 现在想想好水。。按照背包的思路(类似。。反正hobo大神说类似。。)搞搞就有了。。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 1100; const int maxv = 10100; int a[maxn]; int n; int f[maxv]; int smax = 0; void read() { scanf("%d", &n); for(int i = 1; i <= n; ++ i) { scanf("%d", &a[i]); smax = max(smax, a[i]); } } int gcd(int a, int b) { return a % b == 0 ? b : gcd(b, a % b); } void sov() { memset(f, -1, sizeof(f)); for(int i = 1; i <= n; ++ i) { for(int j = 1; j <= smax; ++ j) { if(f[j] != -1 || j == a[i]) { if(f[j] == -1) f[j] = 1; else { if(f[gcd(j, a[i])] == -1) f[gcd(j, a[i])] = f[j] + 1; else f[gcd(j, a[i])] = min(f[gcd(j, a[i])], f[j] + 1); } } } } int G = a[1]; for(int i = 2; i <= n; ++ i) { G = gcd(a[i], G); } printf("%d\n",n - f[G]); } int main() { read(); sov(); return 0; }