2020牛客暑期多校训练营(第三场)(2020.7.18)
开始堇业,把之前欠的债补上。
A、Clam and Fish
有鱼的情况拿饵,后来用饵去换一条鱼实际上就是一换一,没区别。所以有鱼肯定拿鱼。
没鱼的情况有饵肯定拿饵。但这么搞问题是如果全是饵的话就炸了。
所以就是看当前饵能不能把剩下的池子全钓上来鱼,能的话就直接钓鱼了,后面就不需要拿饵了。
这题还哇了好几次,气死我了。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 10;
static char opt[MAXN];
int main()
{
int t; scanf("%d", &t);
while (t--)
{
int len; scanf("%d", &len); vector <int> temp;
scanf("%s", opt);
int ans = 0;
for (int i = 0; i < len; ++i)
if (opt[i] == '2' || opt[i] == '3') ++ans;
else temp.push_back(opt[i] - '0');
int baits = 0, n = temp.size();
for (int i = 0; i < n; ++i)
{
if (n - i - 1 <= baits)
{
ans += baits; break;
}
else
{
if (temp[i] == 0 && baits > 0) ++ans, --baits;
else if (temp[i] == 1) ++baits;
}
}
cout << ans << endl;
}
return 0;
}
B、Classical String Problem
搞个指针记录起始位置,往后往前跳即可。
注意负数。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 10;
int main()
{
static char s[MAXN]; scanf("%s", s); getchar();
int beginner = 0;
int MOD = strlen(s);
int Q; cin >> Q; getchar();
for (int i = 1; i <= Q; ++i)
{
char opt; int num; scanf("%c%d", &opt, &num);
getchar();
if (opt == 'M')
beginner = ((beginner + num) % MOD + MOD) % MOD;
else
printf("%c\n", s[(beginner + num - 1) % MOD]);
}
return 0;
}
C、Operation Love
灵感来源:浩大师。
看这题给的巴掌图的右下角两条边,一条长9,一条长8。而且没有其它边和这两条边长度相同。把这两条边拿出来叉积一下就好了。
代码写得有点麻烦。另外eps要开小一点。
#include <bits/stdc++.h>
using namespace std;
class Point
{
public:
double x, y;
Point() {x = y = 0;}
Point(double a, double b) { x = a; y = b; }
};
const double eps = 1e-3;
int dcmp(double x)
{
if (fabs(x) < eps) return 0;
if (x > 0) return 1;
return -1;
}
Point operator -(Point a, Point b)
{
return Point(a.x - b.x, a.y - b.y);
}
double operator ^(Point a, Point b)
{
return a.x * b.y - a.y * b.x;
}
double operator *(Point a, Point b)
{
return a.x * b.x + a.y * b.y;
}
double abs(Point x)
{
return sqrt(x * x);
}
bool operator ==(Point x, Point y)
{
if (!dcmp(x.x - y.x) && !dcmp(x.y - y.y)) return 1;
return 0;
}
bool operator !=(Point x, Point y)
{
if (x == y) return 0;
else return 1;
}
int main()
{
int t; cin >> t;
while (t--)
{
Point a[30];
for (int i = 1; i <= 20; ++i)
{
Point x; scanf("%lf%lf", &x.x, &x.y);
a[i] = x;
}
vector <Point> vec;
for (int i = 1; i <= 20; ++i)
{
for (int j = 1; j < i; ++j)
{
if (i == j) continue;
if (!dcmp(abs(a[i] - a[j]) - 8) || !dcmp(abs(a[i] - a[j]) - 9))
{
vec.push_back(a[i]); vec.push_back(a[j]);
}
}
}
/*for (auto &i : vec)
{
cout << i.x << ' ' << i.y << endl;
}*/
vector <Point> temp; Point rec;
for (int i = 0; i < vec.size(); ++i)
{
for (int j = 0; j < temp.size(); ++j)
if (vec[i] == temp[j])
rec = vec[i];
temp.push_back(vec[i]);
}
//cout << rec.x << ' ' << rec.y << endl;
Point v1, v2;
for (int i = 0; i < vec.size(); ++i)
if (vec[i] != rec)
{
if (!dcmp(abs(vec[i] - rec) - 8)) v1 = vec[i] - rec;
if (!dcmp(abs(vec[i] - rec) - 9)) v2 = vec[i] - rec;
}
//cout << v1.x << ' ' << v1.y << endl;
//cout << v2.x << ' ' << v2.y << endl;
if ((v1 ^ v2) > 0) cout << "right" << endl;
else cout << "left" << endl;
}
return 0;
}
E、Two Matchings
这题我是真的不会。璇大师把这题转换成了另一个模型,然后dp出来了。具体怎么搞的我也不是很清楚。似乎是四个或者六个为一组dp。代码:璇大师
% 璇大师 %
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
typedef long long ll;
ll dp[200005];
int main()
{
ll T; ll n;
scanf("%lld", &T);
while (T--)
{
scanf("%lld", &n);
vector<ll>q(n); ll sum=0;
for (int i =0; i <n; i++)
{
scanf("%lld", &q[i]);
}
sort(q.begin(), q.end());vector<ll>de; ll ans=0;
for (int i = 1; i < n; i++)
{
int d = q[i] - q[i - 1];
sum += d;
if(i>=4&&i%2==0&&i<=n-4)de.push_back(d);
}
if (de.size() == 0) ans = 0;
else if (de.size() == 1) ans = de[0];
else
{
dp[0] = de[0];
if (de.size() >= 2)dp[1] = max(de[0], de[1]);
if (de.size() >= 3)dp[2] = max(de[1], de[0] + de[2]);
for (int i = 3; i < de.size(); i++)
{
dp[i] = max(dp[i - 2], dp[i - 3]) + de[i];
}
ans = max(dp[de.size() - 1], dp[de.size() - 2]);
}
printf("%lld\n", 2 * sum - 2 *ans);
}
}
L、Problem L is the Only Lovely Problem
乱搞。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
string s; bool flag = true;
cin >> s;
if (s.length() < 6) flag = false;
else
{
for (int i = 0; i < 6; i++)
{
if (s[i] <= 'Z' && s[i] >= 'A')
s[i] += 'a' - 'A';
}
if (s.substr(0, 6) != "lovely")
flag =false;
if (flag) cout << "lovely";
else cout << "ugly";
}
}
赛后总结:
这场思维题其实比较多。比如A和E,CF上面很喜欢出这种题,内味太重。
关键就是贪心和这种要点转化的dp我不是很搞得来。这一部分需要加强。
另外这场很明显能看到我们队队员之间码风差别很大。像璇大师命名变量和数组喜欢用拼音,浩大师的括号不换行等等。魔鬼般的缩进、不用空格格式化和莫名其妙的回车也是普遍存在的问题。
关于码风的问题已经在改了,主要通过每周三题训练。但是似乎队里除了我并没有什么补的积极性(?
过两天还是得检讨一下每周三题效果。目的主要有两个,一是训练思维查漏补缺,二是尽量让队内码风统一。不过这几周看下来码风问题还是很严重,补题只补了思路没改码风。