AtCoder Beginner Contest 157 题解报告

A:Duplex Printing

题目大意 :

给你一个数,一次能打印两面,问表示须要打印多少张才能将全部打印完。

析题得侃 :

若是这个数是偶数, 须要打印 n / 2
若是这个数是奇数, 须要打印 n / 2 + 1.

考察点:

签到,思惟

Code:

#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;
typedef pair<int,int>PII; 

int main(void) {
    int n;
    cin >> n;
    if(n & 1) cout << n / 2 + 1 << endl;
    else cout << n / 2 << endl;
    return 0;
}

B:Bingo

题目大意:

给一个 3 * 3 的矩阵,每一个位置有一个数,以后再给你一些数,若是这些数在这个矩阵中
而且因此数组合到一块儿可使得 有一列或者有一行或者斜对角 都出现过,就输出 Yes,
不然输出 No.

析题得侃:

没有想到好的方法,就一个一个枚举了,hh,方法虽然笨点,总归是 AC 了。

考察点 :

模拟

Code :

#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;
typedef pair<int,int>PII; 

int a[5][5];
int cnt[5][5];

int main(void) {
    for(int i = 1; i <= 3; i ++) {
        for(int j = 1; j <= 3; j ++) {
            cin >> a[i][j];
        }
    }
    int n,value;
    cin >> n;
    while(n --) {
        cin >> value;
        bool vis = false;
        for(int i = 1; i <= 3; i ++) {
            for(int j = 1; j <= 3; j ++) {
                if(a[i][j] == value) {
                    vis = true;
                    cnt[i][j] = 1;
                    break;
                }
            }
            if(vis) break;
        }
    }
    if((cnt[1][1] == 1 && cnt[1][2] == 1 && cnt[1][3] == 1) || (cnt[2][1] == 1 && cnt[2][2] == 1 && cnt[2][3] == 1) ||
        (cnt[3][1] == 1 && cnt[3][2] == 1 && cnt[3][3] == 1) || (cnt[1][1] == 1 && cnt[2][1] == 1 && cnt[3][1] == 1) ||
        (cnt[1][2] == 1 && cnt[2][2] == 1 && cnt[3][2] == 1) || (cnt[1][3] == 1 && cnt[2][3] == 1 && cnt[3][3] == 1) ||
        (cnt[1][1] == 1 && cnt[2][2] == 1 && cnt[3][3] == 1) || (cnt[1][3] == 1 && cnt[2][2] == 1 && cnt[1][3] == 1)
    ) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
    return 0;
}

C:Guess The Number

题目大意:

大概就是说给你一个不超过三位的一个数,而后这以后会有一些操做,能够指定某一位是多少,
可是不容许有前导 0 ,同一个位置不能重复指定,不然会出现错误,除了指定的数外,还要保证
最后获得的数是最小的。

析题得侃:

题是不难,就是细节忒多,须要考虑的状况比较多,这道题我还犯了一个小错误,就是重复输出了,
对于某一种状况没有及时跳出来,致使对某一个测试样例会输出两个答案。不过这道题收获仍是
蛮多的,重要的是学会尝试着去找不一样的状况去接近答案。

考察点:

思惟,模拟

Code:

#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;

int n,m;

int x,b;

int a[4],cnt[4];

int main(void) {
    cin >> n >> m;
    if(n == 1 && m == 0) {
        // 这种状况要及时跳出来,否则就与下面的冲突了 
        cout << 0 << endl;
        return 0;
    }
    bool vis = true;
    while(m --) {
        cin >> x >> b;
        if(vis == false) continue;
        if(n > 1 && x == 1 && b == 0) {
            vis = false;
        } else if(cnt[x] && a[x] != b) {
            vis = false;
        } else {
            a[x] = b;
            cnt[x] = 1;
        }
    }
    if(vis == false) {
        cout << -1 << endl;
    } else {
        for(int i = 1; i <= n; i ++) {
            if(a[1] == 0 && cnt[1] == 0) a[1] = 1;
            cout << a[i] ;
        }
        cout << endl;
    }
    return 0;
}

D:Friend Suggestions

题目大意:

先给一些关系,代表两个数之间是朋友的关系,接着再给一些关系,表示这些人之间不是朋友的
关系,最后问你每一个人能够有多少我的能够是本身的候选朋友(不包括已有的),并且全部人跟
本身还必须是在同一个连通块内的。

析题得侃:

这题是赛后补的,琢磨完第三题剩下的时间就很少了,跟一些大佬真的无法比,不过最后靠本身
的能力把这道题补出来,本身仍是很欣慰的。
一看到这道题涉及到关系,第一时间想到的就是并查集,而后就往哪里想,其实是带权并查集
的初级版,咱们最后求得是候选的朋友,咱们能够求出这个连通块的大小,而后每一个人的朋友就是
当前这个点的出度,还有在同一个连通块中跟这我的也有可能不是朋友,这是咱们能够拿一个
cnt 数组用来计算不是朋友的数量(是双向的,具体的会在代码中体现),而后这个连通块的大小
- 朋友数量 - 不是朋友的数量 = 候选朋友的数量(同一个连通块内)。

考察点:

带权并查集,连通块

Code:

#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;

const int maxn = 1e5 + 10;

int vis[maxn],cnt[maxn];
int fa[maxn],sz[maxn],deg[maxn];

int ans = 0;

int get(int x) {
    return x == fa[x] ? x : fa[x] = get(fa[x]);
}

void Union(int x,int y) {
    int xx = get(x);
    int yy = get(y);
    if(xx == yy) return ;
    fa[yy] = xx;
    sz[xx] += sz[yy];
    return ;
}

int main(void) {
    int n,m,k;
    int u,v;
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i ++) {
        fa[i] = i;
        // 刚开始每一个都是独立的,都是一个 
        sz[i] = 1;

    }
    for(int i = 1; i <= m; i ++) {
        cin >> u >> v;
        // 记录每一个点的出度 
        deg[u] ++;
        deg[v] ++;
        Union(u,v);
    }
    for(int i = 1; i <= k; i ++) {
        cin >> u >> v;
        if(get(u) == get(v)) {
            // 不是朋友,但在同一个连通块内,因此都须要减小 
            cnt[u] --;
            cnt[v] --;
        }
    }
    for(int i = 1; i <= n; i ++) {
        cout << sz[get(i)] - deg[i] + cnt[i] - 1<< " ";
    }
    return 0;
}

E:Simple String Queries

题目大意:

有一串字符,咱们能够执行两种操做:
一、替换某个位置的字符
二、查询某一段区间不一样字符的个数

析题得侃:

很明显:这道题的两种操做分别是:单点修改,区间查询
是否是跟树状数组的基本操做十分的相似,固然,线段树也是能够的,可是杀鸡焉用牛刀,
关键是本身太菜,哈哈。咱们能够用一个二维的数组记录当前位置以前每一个字符出现的数量。
具体实现看代码。

考察点:

树状数组,线段树

Code:

#include <cstdio> 
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 5e5 + 10;

char a[maxn];

int c[maxn][26];

int t,op,pos,l,r,len;
char v;

int lowbit(int x) {
    return x & -x;
}

void insert(int id,int x,int v) {
    for(int i = id; i <= len; i += lowbit(i)) {
        c[i][x] += v;
    }
    return ;
}

int query(int id,int x) {
    int ans = 0;
    // x 表明是( x - 'a') 
    for(int i = id; i; i -= lowbit(i)) {
        ans += c[i][x];
    }
    return ans;
}

int main(void) {
    cin >> len;
    scanf("%s",a + 1);
    for(int i = 1; i <= len; i ++) {
        int v = a[i] - 'a';
        insert(i,v,1);
    }
    cin >> t;
    while(t --) {
        cin >> op; 
        if(op == 1) {
            cin >> pos >> v;
            // 更新 
            insert(pos,a[pos] - 'a',-1);
            insert(pos,v - 'a',1);
            a[pos] = v;                    // 修改后记得修改原数组 
        } else {
            cin >> l >> r;
            int res = 0;
            for(int i = 0; i < 26; i ++) {
                // 若是这个区间有这个字符,只须要 + 一次便可 
                if(query(r,i) - query(l - 1,i)) res ++;
            }
            cout << res << endl;
        }
    }
    return 0;
}

F:Yakiniku Optimization Problem

待补

后记:

本人能力有限,写的不当之处还望各位看官多多指教,如在参考中遇到各类问题,欢迎你们
留言交流,共同交流。
相关文章
相关标签/搜索