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\n", 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\n", 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\n", 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\n", 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\n", r);
    for(int i = 1; i <= q; i ++) if(ans[i]) printf("%d ", i);
    return 0;
} 

原文地址:https://www.cnblogs.com/hongzy/p/12319488.html

时间: 2024-10-30 22:55:16

AtCoder Beginner Contest 155 简要题解的相关文章

AtCoder Grand Contest 038 简要题解

从这里开始 比赛目录 Problem A 01 Matrix Code #include <bits/stdc++.h> using namespace std; typedef bool boolean; const int N = 1e3 + 5; int W, H, A, B; int main() { scanf("%d%d%d%d", &W, &H, &A, &B); for (int i = 0; i < W; i++) {

AtCoder Grand Contest 037 简要题解

从这里开始 题目目录 Problem A Dividing a String 猜想每段长度不超过2.然后dp即可. 考虑最后一个长度大于等于3的一段,如果划成$1 + 2$会和后面相同,那么划成$2 + 1$,如果前一段和前面相同,那么把前一段和前面合并.每次操作后段数都不会减少.所以存在一种最优方案使得每段长度不超过2. Code #include <bits/stdc++.h> using namespace std; typedef bool boolean; const int N =

【ATcoder】AtCoder Beginner Contest 161 题解

题目链接:AtCoder Beginner Contest 161 原版题解链接:传送门 A - ABC Swap 这题太水,直接模拟即可. 1 #include <iostream> 2 using namespace std; 3 int main() { 4 int a, b, c; 5 cin >> a >> b >> c; 6 swap(a, b); 7 swap(a, c); 8 cout << a << " &

AtCoder Beginner Contest 154 题解

人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We have A balls with the string S written on each of them and B balls with the string T written on each of them. From these balls, Takahashi chooses one

AtCoder Beginner Contest 136

AtCoder Beginner Contest 136 Contest Duration : 2019-08-04(Sun) 20:00 ~ 2019-08-04(Sun) 21:40 Website: AtCoder BC-136 后面几题都挺考思考角度D. C - Build Stairs 题目描述: 有n座山从左到右排列,给定每一座山的高度\(Hi\),现在你可以对每座山进行如下操作至多一次:将这座山的高度降低1. 问是否有可能通过对一些山进行如上操作,使得最后从左至右,山的高度呈不下降

AtCoder Beginner Contest 103 D(贪心)

AtCoder Beginner Contest 103 D 题目大意:n个点,除第n个点外第i与第i+1个点有一条边,给定m个a[i],b[i],求最少去掉几条边能使所有a[i],b[i]不相连. 按右端点从小到大排序,如果当前选的去掉的边在区间内,那么符合条件,否则ans++,并贪心地把去掉的边指向右端点,因为前面的区间都满足条件了,所以要去掉的边要尽量向右移使其满足更多的区间. 1 #include <iostream> 2 #include <cstdio> 3 #incl

AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)

AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质) We have a tree with NN vertices numbered 11 to NN. The ii-th edge in this tree connects Vertex aiai and Vertex bibi. Consider painting each of these edges white or black. There ar

AtCoder Beginner Contest 115 题解

题目链接:https://abc115.contest.atcoder.jp/ A Christmas Eve Eve Eve 题目: Time limit : 2sec / Memory limit : 1024MB Score : 100 points Problem Statement In some other world, today is December D-th. Write a program that prints Christmas if D=25, Christmas E

AtCoder Beginner Contest 121 题解

题目链接:https://atcoder.jp/contests/abc121 A White Cells 分析:题目数据规模很小,直接暴力修改都可以.或者可以推出公式. 代码: 1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int a[25][25] = {0}; 9 int H, W, h, w; 10 scanf("%d %d"