Codeforces Round 964 div4

nnnnakosuki發表於2024-08-08

Codeforces Round 964 div4

第一次vp,也是第一次打div4,並不是很清楚難度如何,所以vp時經常把題目想的過於複雜,同時手速碼力還是有點弱,感覺有時候會很 混亂


A. A+B Again?

https://codeforces.com/contest/1999/problem/A

兩位數直接對10求除和模即可,即 $ ans = n\div 10 + n\bmod 10 $,我vp時思路直接對數進行除

B. Card Game

https://codeforces.com/contest/1999/problem/B

題意:兩個人各有兩個手牌,然後任意順序安排手牌順序去比較,每次出一張,比對方的手牌大則獲勝,相等平局,否則則輸,只有兩次比較後比分比對方大這局才獲勝,因此我們求可能的獲勝局數。
一開始的想法就是直接用next_permutation寫模擬,結果腦袋不清醒沒想好怎麼打,後來想到只需要寫二重迴圈,沒選中的牌進行比較即可,這裡也因為是2個所以可以透過對2求模來找到未被選中的牌

void solve() {
    int a[2],b[2];
    std::cin >> a[0] >> a[1] >> b[0] >> b[1];
    int ans = 0;
    for(int i = 0;i <= 1;i ++ )
        for(int j = 0;j <= 1;j ++ ) {
            int cnt = 0;
            if(a[i] > b[j]) cnt ++;
            else if(a[i] < b[j]) cnt --;
            if(a[(i + 1) % 2] > b[(j + 1) % 2]) cnt ++;
            else if(a[(i + 1) % 2] < b[(j + 1) % 2]) cnt --;
            // std::cout << cnt << "\n";
            if(cnt > 0) ans ++;
        }
    std::cout << ans << "\n";
}   

C. Showering

https://codeforces.com/contest/1999/problem/C

這題真是唐中唐,不知道為什麼上來就開始寫差分,後來發現對端點差分不好判斷長度,遂直接對線段按做端點排序直接判斷兩個線段間隔是否滿足,同時注意第一條線段需不需要和0比較與最後一條線段需不需要和1比較

int n,s,m,d[N];
std::vector<PII> vc;
void solve() {
    std::cin >> n >> s >> m;
    vc.clear();
    if(s > m) std::cout << "No" << "\n";
    else {
        for(int i = 1;i <= n;i ++ ) {
            int l,r;
            std::cin >> l >> r;
            vc.push_back({l,r});
        }
        std::sort(vc.begin(),vc.end());
        int pre = 0;
        bool flag = false;
        for(auto i : vc) {
            auto t = i;
            if(i.first == 0) {
                pre = i.second;
                continue;
            } else {
                int wait = i.first - pre;
                if(wait >= s) {
                    flag = true;
                    break;
                } else pre = i.second;
            }
        }
        if(pre != m && m - pre >= s) flag = true;
        std::cout << (flag ? "Yes" : "No") << "\n";
    }
}

D. Slavic's Exam

https://codeforces.com/contest/1999/problem/D

題意:給一個含?的字串a與字串b,?可以任意改,是否能夠讓b成為a的子序列
思路:依次在a中比較b的每個字元,如果是?則將其改為對應的b中的字元。之後在直接判斷b是否是a的子序列,具體實現是雙指標
寫完C就已經3點多了,腦子著實有點不清醒了,所以調的就開始很慢了(還是太菜了)

std::string a,b;
void solve() {
    std::cin >> a;
    std::cin >> b;
    int j = 0;
    for(auto &i : a) {
        if(j == b.size()) break;
        if(i == b[j]) {
            j ++;
            continue;
        }
        if(i == '?') i = b[j ++];
    }
    j = 0;
    for(int i = 0;i < a.size();i ++ ) {
        if(a[i] == b[j]) j ++;
        else if(a[i] == '?') a[i] = a[i - 1];
    }
    if(j >= b.size()) {
        std::cout << "YES\n";
        for(auto i : a)
            std::cout << i;
        std::cout << "\n";
    }else std::cout << "NO\n";
}

E. Triple Operations

https://codeforces.com/contest/1999/problem/E

題意:給一個序列,選擇一對數 \(x\),\(y\) 進行一次操作後則變為 \(3x\),\(\left\lfloor\frac{y}{3}\right\rfloor\)
思路:先選取最小的數操作至0,之後的操作就是選取0與其他非0數進行操作,需要注意的是操作最小數時會同時乘對應次數的3,只需要算出最小數操作為0的次數乘2即可。因為是算從 \(l\)\(r\) 的數的操作的次數,因此我們可以透過字首和來進行最佳化。
求一個數操作為0的次數可以先預處理出來 \(F\left[i\right] = 3 ^ i\),因為是從 \(l\)\(r\) 是連續的,因此我們只需要 \(O\left( n \right)\) 的複雜度就可以處理出來

const int N = 200010, INF = 0x7fffffff,Mod = 998244353;
int l,r,f[13],p[N];
void init() {
    f[0] = 1;
    for(int i = 1;i <= 13;i ++ )
        f[i] = f[i - 1] * 3;
}
void init_() {
    p[0] = 0;
    p[1] = 1;
    int pre = 1;
    for(int i = 2;i <= 200010;i ++ ) {
        if(f[pre] <= i) pre ++;
        p[i] = pre;
        p[i] += p[i - 1];
    }
}
void solve() {
    std::cin >> l >> r;
    int ans = 0;
    ans += p[r] + p[l] - 2 * p[l - 1];
    std::cout << ans << "\n";
}

signed main() {
    FastIO;
    // freopen("in.txt", "r", stdin);
    // freopen("me.txt", "w", stdout);
    int _;
    _= 1;
    std::cin >> _;
    init();
    init_();
    while(_ --)
    {
        solve();
    }
    return 0;
}

相關文章