牛客周賽 Round 56

KXDdesu發表於2024-08-19

寫在前面

這場難度不是很高
少見的周賽出了模擬題,還是很好寫的,有一點小小的坑
最後一題是個字串雜湊
其他題都是比較偏思維的

程式碼需要手動展開!!!

A題

直接判斷 x + y 與 n 的關係即可

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int x, y, n;
    std::cin >> x >> y >> n;
    if (x + y <= n) {
    	std::cout << "YES\n";
    }
    else {
    	std::cout << "NO\n";
    }
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

B題

注意是m個人和小S一起留下了
所以一共是留下了m + 1個人
一共可以做sum / k個紙飛機
輸出min(m + 1, sum / k)即可
注意會溢位int,開long long

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<int> a(n);
    int sum = 0;
    for (int i = 0; i < n; i ++) {
    	std::cin >> a[i];
    	sum += a[i];
    }
    std::cout << std::min(m + 1, sum / k) << '\n';
}
signed main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

C題

首先想到的是一個數是1,另一個數是(1 xor a)
但是發現有兩個特例
當a == 1時,1 xor a 是 0,不是正整數,但是樣例給了,直接輸出2和3即可
當a == 1e9時,1 xor a 是 1e9 + 1,大於了1e9,透過對10,100進行打表
可以選擇一個數是a - 1,那麼另一個數就是(1e9 xor (a - 1))

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int a;
    std::cin >> a;
    if (a == 1) {
        std::cout << 2 << ' ' << 3 << '\n';
    } 
    else if (a != (int)(1e9)) {
        std::cout << 1 << " " << (1 ^ a) << '\n';
    }
    else {
        int x = (int)(1e9) - 1;
        int s = 1e9;
        std::cout << x << " " << (x ^ s) << '\n';
    }
}
signed main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    std::cin >> T;
    while (T --) solve();
    return 0;
}

D題

三角形的三邊a, b, c(a <= b <= c)滿足 a + b > c
那麼可以對邊進行排序,每次判斷相鄰的三條邊
證明
如果a[i], a[i + 1], a[i + 2]不滿足
a[i - 1], a[i + 1], a[i + 2]一定不滿足
如果a[i - 1], a[i + 1], a[i + 2]滿足
a[i], a[i + 1], a[i + 2]一定滿足

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; i ++) {
    	std::cin >> a[i];
    }
    std::sort(all(a));
    int max = -1;
    for (int i = 0; i + 2 < n; i ++) {
    	if (a[i] + a[i + 1] > a[i + 2]) {
    		max = std::max(max, a[i] + a[i + 1] + a[i + 2]);
    	}
    }
    std::cout << max << '\n';
}
signed main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    std::cin >> T;
    while (T --) solve();
    return 0;
}

E題

模擬題,按題意寫就可以
判斷是否是開心的時間段,可以用差分陣列來維護,然後O(1)判斷
時間的輸入可以用scanf("%d:%d", &h, &m)
時間前後的判斷,可以轉換成分鐘進行判斷
奶茶是否是喜歡的,用set維護就行
注意一個點,輸入的開心時間段可能存在開始時間的分鐘數大於結束的分鐘數
如下圖

對這種時間段進行差分的時候,注意一下即可

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n, m;
    std::cin >> n >> m;
    std::vector<int> b(24 * 60 + 2);
    for (int i = 0; i < n; i ++) {
    	int h1, m1, h2, m2;
    	scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2);
    	int s = h1 * 60 + m1;
    	int t = h2 * 60 + m2;
    	if (s == t) {
    		b[0] ++;
    	}
    	b[s] ++;
    	b[t + 1] --;
    }
    for (int i = 1; i <= 24 * 60; i ++) {
    	b[i] += b[i - 1];
    }
    std::set<std::string> st;
    for (int i = 0; i < m; i ++) {
    	std::string s;
    	std::cin >> s;
    	st.insert(s);
    }
    int q;
    std::cin >> q;
    while (q --) {
    	int h, m;
    	scanf("%d:%d", &h, &m);
    	int t = h * 60 + m;
    	int h1, m1, h2, m2;
    	scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2);
    	int t1 = h1 * 60 + m1;
    	int t2 = h2 * 60 + m2;
    	std::string s;
    	std::cin >> s;
    	if (!(t >= 0 && t <= 60 + 59)) {
    		std::cout << "Loser xqq\n";
    		continue;
    	}
    	if (b[t] == 0) {
    		std::cout << "Loser xqq\n";
    		continue;
    	}
    	if (t1 > t2) {
    		std::cout << "Joker xqq\n";
    		continue;
    	}
    	if (!st.count(s)) {
    		std::cout << "Joker xqq\n";
			continue;
    	}
    	std::cout << "Winner xqq\n";
    }
}
int main()
{
    // std::cin.tie(nullptr);
    // std::cout.tie(nullptr);
    // std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

F題

二分+字串雜湊
本題會卡自然溢位hash
組題人原話

對s,t,以及翻轉後的s進行雜湊
雜湊陣列分別是hs[], ht[], rhs[]
然後遍歷翻轉點,然後二分lcp長度
判斷lcp是否相等
翻轉點是id,二分的lcp長度是x
t的好說,直接可以求出來
gethash(ht, 1, x)
s的判斷情況
二分的長度在翻轉區間內,即 x <= id
gethash(rhs, n - id + 1, n - id + x)
否則是
gethash(rhs, n - id + 1, n) * p[x - id] + gethash(hs, id + 1, x)

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using u64 = unsigned long long;
using pii = std::pair<int, int>;
const int P = 13331;
const i64 mod = 1610612741;
void solve()
{
    int n;
    std::cin >> n;
    std::string s, t;
    std::cin >> s >> t;
    std::vector<i64> p(n + 1), hs(n + 1), rhs(n + 1), ht(n + 1);
    p[0] = 1;
    for (int i = 0; i < n; i ++) {
        p[i + 1] = p[i] * P % mod;
        hs[i + 1] = (hs[i] * P + s[i]) % mod;
        ht[i + 1] = (ht[i] * P + t[i]) % mod;
    }
    std::reverse(all(s));
    for (int i = 0; i < n; i ++) {
        rhs[i + 1] = (rhs[i] * P + s[i]) % mod;
    }
    int max = -1;
    int pos = 0;
    auto gethash = [&](std::vector<i64>& h, int l, int r) -> i64 {
        return ((h[r] - h[l - 1] * p[r - l + 1]) % mod + mod) % mod;
    };  
    auto check = [&](int id, int x) -> bool {
        u64 S;
        if (x <= id) {
            S = gethash(rhs, n - id + 1, n - id + x);
        }
        else {
            S = (gethash(rhs, n - id + 1, n) * p[x - id] % mod + gethash(hs, id + 1, x)) % mod;
        }
        u64 T = ht[x];
        // std::cerr << S << " " << T << '\n';
        return S == T;
    };
    for (int i = 1; i <= n; i ++) {
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            // std::cerr << l << " " << r << " " << mid << '\n';
            if (check(i, mid)) {
                l = mid;
            }
            else {
                r = mid - 1;
            }
        }
        // std::cerr << l << "\n\n";
        if (max < l) {
            max = l;
            pos = i;
        }
    }
    std::cout << max << ' ' << pos << '\n';
    // std::cerr << '\n';
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    std::cin >> T;
    while (T --) solve();
    return 0;
}