日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

AtCoder Beginner Contest 329 (ABC329)

發布時間:2023/11/21 windows 79 coder
生活随笔 收集整理的這篇文章主要介紹了 AtCoder Beginner Contest 329 (ABC329) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

A. Spread

不說了,代碼。

B. Next

不說了,代碼。

C. Count xxx

Description

給定一個長度為 \(N\) 的字符串 \(S\),求 \(S\)非空連續,并且包含重復字符的連續子串長度。

例如 $S = $ aaabaa,則它滿足上述條件子串為 aaaaaab

Solution

這道題 \(1 \le N \le 2 \times 10 ^ 5\),顯然不能暴力。

考慮如何優化。

維護數組 \(v\)\(v_i\) 表示 \(S\) 中子串的重復字符為 \(i\) 的子串長度。

我們循環這個字符串,記錄兩個變量 lstclstnum,分別表示字符串 \(S\) 的上一個字符,和當前連續子串的長度。

如果我們發現,s[i] == lstc,則 lstnum++。否則,lstnum = 1lstc = s[i]

每次循環 v[lstc] = max(v[lstc],lstnum)

最后循環字符 a ~ z,累加 \(v_i\) 即可。

Code
#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 10;
int n, ans, v[300];
char s[N];

int main() {
    scanf("%d", &n);
    scanf("%s", s + 1);
    char lstc = 0;
    int lstnum = 0;
    for (int i = 1; i <= n; ++i) {
        if (s[i] == lstc) {
            ++lstnum;
        } else {
            lstnum = 1;
            lstc = s[i];
        }
        v[lstc] = max(v[lstc], lstnum);
    }
    int ans = 0;
    for (int i = 'a'; i <= 'z'; ++i) {
        ans += v[i];
    }
    printf("%d", ans);
    return 0;
}

D. Election Quick Report

Description

\(N\) 個人,編號 \(1 \sim N\)。每次會將票投給某一個人,輸出投票后票數最大值的人的編號。如果票數相同,輸出編號小的。

Solution

每次記錄一個桶,動態維護當前票數的最大值,位置即可。

如果當前的票數大于最大值,或者當前票數等于最大值但是編號小于最大值,則講最大值更改為當前的票數,并且將位置更改為當前的位置。

每次詢問輸出位置即可。

Code
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;
int n, m, a[N], cnt[N], ma = 0, p;

int main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		scanf("%d", &a[i]);
		cnt[a[i]]++;
		if (cnt[a[i]] > ma || (cnt[a[i]] == ma && a[i] < p)) {
			ma = cnt[a[i]];
			p = a[i];
		}
        printf("%d\n", p);
	}
	return 0;
}

E. Stamp

Description

有兩個字符串 \(S\)\(T\),還有一個長度為 \(N\) 的僅由字符 # 構成的字符串 \(X\)

現在可以執行若干次操作,每次可以選擇字符串 \(X\) 中連續的 \(M\) 段覆蓋為 \(T\)

求:是否能通過若干次操作,使得 \(X\)\(S\) 相等。

Solution

考慮一個覆蓋時間的序列(欽定每一次覆蓋記錄在其右端點上),發現對于當前點 \(p\)

只有 \([p,p+m-1]\) 這一段區間會影響該點的取值,考慮爆搜,對于當前位置p,只需要考慮 \([p-m+1,p]\) 這一段長度為m的時間序列,枚舉當前一個新的位置的相對時間排名,確定下來 \([p-m+1,p]\) 的相對時間順序,于是位置 \(p-m+1\) 的值會被 \([p-m+1,p]\) 中時間值最大的點覆蓋掉,再判斷 \(p-m+1\) 的值是否與 \(S\) 串對應位置相等即可。

考慮優化:當前狀態包含當前位置 \(p\),和前面的時間序列 \(st\),若之前已經走到過 <p,st> 這樣一個狀態,那當前就沒必要繼續往下搜了。

Code
#include <bits/stdc++.h>

using namespace std;

unordered_map<int, int> mp;
int n, m;

int gethash(int now, int stat[5]) {
    int hsh = now;
    for (int i = 0; i < m - 1; i++) hsh = hsh * m + stat[i];
    return hsh;
}

char s[200055];
char t[55];

bool search(int now, int stat[5]) {
    int hsh = gethash(now, stat);
    if (mp.find(hsh) != mp.end()) return false;
    mp[hsh] = 1;
    if (now == n + 1) {
        char x[6];
        for (int j = 1; j < m; j++) {
            for (int k = 0; k < m - 1; k++) {
                if (stat[k] == j) {
                    for (int l = 2; l <= m - k; l++) {
                        x[l] = t[l + k];
                    }
                }
            }
        }
        for (int i = 2; i <= m; i++) if (s[n + i - m] != x[i]) return false;
        return true;
    }
    for (int i = 1; i <= m; i++) {
        int new_stat[5];
        new_stat[0] = i;
        for (int j = 1; j < m; j++) {
            new_stat[j] = stat[j - 1];
            if (stat[j - 1] >= i) ++new_stat[j];
        }
        bool flag = true;
        for (int j = 0; j < m; j++) {
            if (new_stat[j] == m) {
                if (s[now - m + 1] != t[j + 1]) flag = false;
            }
        }
        if (!flag) continue;
        for (int j = 0; j < m - 1; j++) {
            if (new_stat[j] > new_stat[m - 1]) --new_stat[j];
        }
        if (search(now + 1, new_stat)) return true;
    }
    return false;
}

int stat[5];
int main() {
    cin >> n >> m;
    scanf("%s%s", s + 1, t + 1);
    if (s[1] != t[1]) {
        puts("No");
        return 0;
    }
    for (int i = 0; i < 5; i++) stat[i] = m - i - 1;
    if (search(m + 1, stat)) {
        printf("Yes");
        return 0;
    }
    printf("No");
    return 0;
}

F. Colored Ball

Description

\(N\) 個箱子,編號為 \(1 \sim N\)。每個箱子初始有一個小球,顏色為 \(C_i\)

現在有 \(Q\) 次詢問,每次輸入一個二元組 \((a,b)\),表示將編號為 \(a\) 的箱子里的所有小球移動到箱子 \(b\) 后,詢問箱子 \(b\) 中有多少種不同顏色的小球。

Solution

這道題用 set 的暴力模擬法,時間復雜度約為 \(O(n ^ 2 \times \log n)\),肯定超時。

可以加上優化:set 的啟發式合并。

即每次將小的箱子移動到大的箱子里面,這樣花費的時間會大大減少,時間復雜度達到了 \(O(n)\)

只需要在代碼中加入一句話:

if (st[x].size() > st[y].size()) swap(st[x], st[y]);

這樣就實現了啟發式合并,可以通過。

Code
#include <bits/stdc++.h>

using namespace std;

const int N = 200010;
int n, q, a[N], x, y;
unordered_set<int> st[N];

int main() {
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		st[i].insert(a[i]);
	}
	while (q--) {
		scanf("%d%d", &x, &y);
		if (st[x].size() > st[y].size()) swap(st[x], st[y]);
		while (st[x].size()) {
			int t = *st[x].begin();
			st[x].erase(t);
			st[y].insert(t);
		}
		printf("%d\n", (int)st[y].size());
	}
	return 0;
}

總結

以上是生活随笔為你收集整理的AtCoder Beginner Contest 329 (ABC329)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。