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

待補

後記:

本人能力有限,寫的不當之處還望各位看官多多指教,如在參考中遇到各類問題,歡迎你們
留言交流,共同交流。
相關文章
相關標籤/搜索