AtCoder Beginner Contest 155 简要题解
Posted hongzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 155 简要题解相关的知识,希望对你有一定的参考价值。
AtCoder Beginner Contest 155
A:签到失败,WA一次。
int main() {
int a, b, c;
cin >> a >> b >> c;
if(a == b && b == c) cout << "No";
else if(a == b || a == c || b == c) cout << "Yes";
else cout << "No";
return 0;
}
B:签到失败乘2,这题又WA一次。
int main() {
int n; scanf("%d", &n); bool ok = 1;
while(n --) {
int x; scanf("%d", &x);
if(x % 2 == 0 && (x % 3 != 0 && x % 5 != 0)) {
ok = 0;
}
}
puts(ok ? "APPROVED" : "DENIED");
return 0;
}
C:直接开map。
string s[200010];
vector<string> vec;
map<string, int> Map;
int main() {
int n; scanf("%d", &n); int ans = 0;
for(int i = 1; i <= n; i ++) {
cin >> s[i];
ans = max(ans, ++ Map[s[i]]);
}
for(int i = 1; i <= n; i ++) {
if(Map[s[i]] == ans) {
Map[s[i]] = 0;
vec.pb(s[i]);
}
}
sort(vec.begin(), vec.end());
for(auto s : vec) printf("%s
", s.c_str());
return 0;
}
D:二分 + two-pointer,正负要讨论,注意不要使用实数运算求floor和ceil。代码非常丑。
const int N = 2e5 + 10;
int n, rpos, a[N]; ll k;
ll C(ll n) { return n * (n - 1) / 2; }
ll fl(ll a, ll b) {
bool f = (a < 0) ^ (b < 0);
if(a < 0) a = -a;
if(b < 0) b = -b;
return f ? - ( a / b + 1 ) : a / b;
}
ll cl(ll a, ll b) {
bool f = (a < 0) ^ (b < 0);
if(a < 0) a = -a;
if(b < 0) b = -b;
return f ? - ( a / b ) : (a + b - 1) / b;
}
int main() {
scanf("%d%lld", &n, &k);
for(int i = 1; i <= n; i ++) scanf("%d", a + i);
sort(a + 1, a + n + 1);
ll l = 0, r = 0, z = 0, L = 0, R = 0, Z = 0;
for(int i = 1; i <= n; i ++) z += a[i] == 0;
for(int i = 1; i <= n; i ++) l += a[i] < 0;
for(int i = 1; i <= n; i ++) r += a[i] > 0;
L = l * r; R = C(l) + C(r); Z = C(n) - L - R;
rpos = n + 1;
for(int i = 1; i <= n; i ++) if(a[i] > 0) {
rpos = i; break ;
}
if(k <= L) {
ll ql = -1e18, qr = -1, mid, ans = -233;
while(ql <= qr) {
mid = (ql + qr) >> 1;
ll sum = 0, now = r, cur = rpos;
for(int i = 1; i <= n && a[i] < 0; i ++) {
ll up = mid % a[i] == 0 ? mid / a[i] + 1 : cl(mid, a[i]);
while(now && a[cur] < up) cur ++, now --;
sum += now;
}
if(sum < k) ql = (ans = mid) + 1;
else qr = mid - 1;
}
printf("%lld
", ans);
} else if(k <= L + Z) {
puts("0");
} else {
k -= L + Z;
ll ql = 1, qr = 1e18, mid, ans = -233;
while(ql <= qr) {
mid = (ql + qr) >> 1;
ll sum = 0, now = r, cur = n;
for(int i = rpos; i <= n; i ++) {
ll up = mid % a[i] == 0 ? mid / a[i] - 1 : fl(mid, a[i]);
while(now && a[cur] > up) cur --, now --;
sum += cur >= i ? now - 1 : now;
}
now = l; cur = 1;
for(int i = n; i >= 1; i --) if(a[i] < 0) {
ll up = mid % a[i] == 0 ? mid / a[i] + 1 : cl(mid, a[i]);
while(now && a[cur] < up) cur ++, now --;
sum += cur <= i ? now - 1 : now;
}
sum >>= 1;
if(sum < k) ql = (ans = mid) + 1;
else qr = mid - 1;
}
printf("%lld
", ans);
}
return 0;
}
E:dp[i][0/1]表示前i位,第i位要不要借给下一位,最小代价。
char s[N];
int dp[N][2];
bool ok(int x) { return x >= 0 && x < 10; }
int main() {
scanf("%s", s + 1);
int n = strlen(s + 1);
dp[0][1] = 1; dp[0][0] = 0;
for(int i = 1; i <= n; i ++) {
dp[i][0] = dp[i][1] = 1e9;
int x = s[i] - '0';
for(int j = 0; j < 10; j ++) {
if(ok(10 + j - x)) dp[i][0] = min(dp[i][0], dp[i - 1][1] + j + (10 + j - x));
if(ok(j - x)) dp[i][0] = min(dp[i][0], dp[i - 1][0] + j + (j - x));
if(ok(10 + (j - 1) - x)) dp[i][1] = min(dp[i][1], dp[i - 1][1] + j + (10 + j - 1 - x));
if(ok(j - 1 - x)) dp[i][1] = min(dp[i][1], dp[i - 1][0] + j + (j - 1 - x));
}
}
printf("%d
", dp[n][0]);
return 0;
}
F:差分,然后区间xor变成两点同时xor。所有l和r+1连边建图,问题转换为选若干条边,一条边被选两个端点就xor上1。
对于每个连通块dfs,如果当前子树的根状态为1就选这条边,否则不选,这样若不合法只可能根不合法。若根不合法,显然无解,因为若要选非dfs树边,一定会出现其他不合法点。
const int N = 2e5 + 10;
struct node {
int a, b;
} x[N], t[N];
int n, q, b[N];
bool ans[N], st[N], vis[N];
vector<pii> G[N];
int get(int u) { return lower_bound(b + 1, b + n + 1, u) - b; }
int getl(int u) { return upper_bound(b + 1, b + n + 1, u) - b - 1; }
void link(int u, int v, int w) { G[u].pb(pii(v, w)); G[v].pb(pii(u, w)); }
int dfs(int u) {
vis[u] = 1; int x = st[u];
for(auto v : G[u]) if(!vis[v.fs]) {
if(dfs(v.fs)) { ans[v.sc] = 1; x ^= 1; }
}
return x;
}
int main() {
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i ++) { scanf("%d%d", &x[i].a, &x[i].b); b[i] = x[i].a; }
for(int i = 1; i <= q; i ++) scanf("%d%d", &t[i].a, &t[i].b);
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; i ++) { x[i].a = get(x[i].a); st[x[i].a] = x[i].b; }
for(int i = n + 1; i >= 1; i --) st[i] ^= st[i - 1];
for(int i = 1; i <= q; i ++) link(get(t[i].a), 1 + getl(t[i].b), i);
for(int i = 1; i <= n + 1; i ++) if(!vis[i]) {
if(dfs(i)) { puts("-1"); return 0; }
}
int r = 0;
for(int i = 1; i <= q; i ++) r += ans[i];
printf("%d
", r);
for(int i = 1; i <= q; i ++) if(ans[i]) printf("%d ", i);
return 0;
}
以上是关于AtCoder Beginner Contest 155 简要题解的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解