2020牛客暑期多校训练营(第三场)
A-Clam and Fish
https://ac.nowcoder.com/acm/contest/5668/A
题意
给出一个字符串,每一位代表一个状态,0代表没有鱼也没有无法获得鱼饵,1代表没有鱼但可以获得鱼饵,2代表有鱼无法获得鱼饵,3代表既有鱼又可以获得鱼饵,如果有鱼可以直接钓鱼,有鱼饵可以获得一个鱼饵,可以消耗一个鱼饵钓鱼,每个状态只可以进行一次操作,问最多能钓上多少鱼
题解
能直接钓鱼就直接钓鱼,对于鱼饵,先在那些无法获得鱼饵的池子消耗鱼饵钓鱼,再加上剩下的鱼饵除以2向下取整即为答案
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
inline char read() {
#ifdef _WIN32
return getchar();
#endif
static const int IN_LEN = 1 << 18 | 1;
static char buf[IN_LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
}
template <typename _Tp> inline READ & operator >> (_Tp&x) {
static char c11, boo;
for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
if(c11 == -1) return *this;
boo |= c11 == '-';
}
for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
boo && (x = -x);
return *this;
}
} in;
const int N = 2e6 + 50;
char s[N];
int main() {
int t; scanf("%d", &t);
while (t--) {
int n; scanf("%d", &n);
scanf("%s", s + 1);
int now = 0, ans = 0;
for (int i = 1; i <= n; i++) {
if (s[i] == '0') if (now > 0) now--, ans++;
if (s[i] == '1') now++;
if (s[i] == '2') ans++;
if (s[i] == '3') ans++;
}
ans += now / 2;
printf("%d\n", ans);
}
return 0;
}
B-Classical String
https://ac.nowcoder.com/acm/contest/5668/B
题意
给出一个字符串,2种操作
M x,如果x大于0,把前缀长度为x的字符串移到最后,否则把前缀长度为\(|x|\)的后缀移到最前面
A x,询问x位置的字符是什么
题解
维护修改操作的前缀和,可以发现前缀和的值等价于修改的总和,从当前前缀和的位置向后找即可,直接取模
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
struct READ {
inline char read() {
#ifdef Artoriax
return getchar();
#endif
const int LEN = 1 << 18 | 1;
static char buf[LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
}
inline READ & operator >> (char *s) {
char ch;
while (isspace(ch = read()) && ~ch);
while (!isspace(ch) && ~ch) *s++ = ch, ch = read(); *s = '\0';
return *this;
}
inline READ & operator >> (string &s) {
s = ""; char ch;
while (isspace(ch = read()) && ~ch);
while (!isspace(ch) && ~ch) s += ch, ch = read();
return *this;
}
template <typename _Tp> inline READ & operator >> (_Tp&x) {
char ch, flag;
for(ch = read(),flag = 0; !isdigit(ch) && ~ch; ch = read()) flag |= ch == '-';
for(x = 0; isdigit(ch); ch = read()) x = x * 10 + (ch ^ '0');
flag && (x = -x);
return *this;
}
} in;
const int N = 2e6 + 50;
char s[N];
int main() {
in >> s;
int len = strlen(s);
int m; in >> m;
int now = 0;
while (m--) {
char ch[2]; in >> ch;
int x; in >> x;
if (ch[0] == 'M') now = (now + x) % len;
else {
int pos = (now + x - 1 + len) % len;
printf("%c\n", s[pos]);
}
}
return 0;
}
C-Operation Love
https://ac.nowcoder.com/acm/contest/5668/C
题意
给出一个手的多边形的20个点,判断这个多边形是左手还是右手,可能有旋转和平移
题解
发现长度为9和8的线段是唯一的,把点改为逆时针顺序,直接判断是否有连续的9和8即可
判断给出的多边形是顺时针还是逆时针:
直接计算多边形面积,如果值为负,则为顺时针,否则为逆时针
计算多边形面积,按给出的点的顺序做叉积相加除以2,即为多边形面积。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 2e5 + 50;
const db eps = 1e-5;
int sgn(db x) {
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
else return 1;
}
struct point {
db x, y;
void read() { scanf("%lf%lf", &x, &y); }
db operator ^ (const point &b) const {
return x * b.y - y * b.x;
}
db dis(point b) {
return hypot(x - b.x, y - b.y);
}
} p[25];
int main() {
int t; scanf("%d", &t);
while (t--) {
for (int i = 0; i < 20; i++) p[i].read();
p[20] = p[0];
db s = 0;
for (int i = 0; i < 20; i++) s += p[i] ^ p[i + 1];
if (s < 0) reverse(p, p + 20);
p[20] = p[0], p[21] = p[1];
for (int i = 0; i < 20; i++) {
if (sgn(p[i].dis(p[i+1]) - 9) == 0) {
if (sgn(p[i+1].dis(p[i+2]) - 8) == 0) puts("right");
else puts("left");
}
}
}
return 0;
}
D-Point Construction Problem
https://www.cnblogs.com/artoriax/p/13589527.html
E-Two Matchings
https://www.cnblogs.com/artoriax/p/13589731.html
F-Fraction Construction-Problem
https://www.cnblogs.com/artoriax/p/13589878.html
G-Operating on a Graph
题意
题解
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
inline char read() {
#ifdef _WIN32
return getchar();
#endif
static const int IN_LEN = 1 << 18 | 1;
static char buf[IN_LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
}
template <typename _Tp> inline READ & operator >> (_Tp&x) {
static char c11, boo;
for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
if(c11 == -1) return *this;
boo |= c11 == '-';
}
for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
boo && (x = -x);
return *this;
}
} in;
const int N = 8e5 + 50;
vector<int> G[N];
int f[N];
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(vector<int> &x, vector<int> &y) {
if (x.size() < y.size()) swap(x, y);
for (auto e : y) x.push_back(e);
y.clear();
}
int main() {
int t; in >> t;
while (t--) {
int n, m; in >> n >> m;
for (int i = 1; i <= n; i++) G[i].clear(), f[i] = i;
for (int i = 1; i <= m; i++) {
int x, y; in >> x >> y; x++; y++;
G[x].push_back(y);
G[y].push_back(x);
}
int q; in >> q;
while (q--) {
int o; in >> o; o++;
if (find(o) != o) continue;
vector<int> tmp = G[o];
G[o].clear();
for (auto nx : tmp) {
int y = find(nx);
if (y == o) continue;
f[y] = o;
merge(G[o], G[y]);
}
}
for (int i = 1; i <= n; i++) {
printf("%d ", find(i) - 1);
}
puts("");
}
return 0;
}