天天看點

Educational Codeforces Round 101 (Rated for Div. 2) A-D

A.Regular Bracket Sequence

題解:

這個題目一開始WA了兩發的原因很玄學:沒有看出來他的

()

隻有一對…

那麼在

()

有且僅有一對的情況下,我們首先判斷目前字元串的長度是不是偶數,也就是判斷 l e n m o d    2 = = 0 len\mod 2 == 0 lenmod2==0,如果目前字元串的長度非偶,那麼就可以直接

say no

了,否則我們就讓前一半的

?

變成

(

,後一半變成

)

然後用一個

stack

就可以了

AC代碼

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -1e12
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)

using namespace std;

const int maxn = 1e3 + 10;

int t;
string s;
stack<char> st;

int main()
{
    ios;
    cin >> t;
    while(t--) {
        cin >> s;
        bool flag = 1;
        int len = s.length();
        if(len % 2 != 0) {
            cout << "NO" << endl;
            continue;
        }
        else {
            int num = (len - 2) / 2,cnt = 0;
            for(int i = 0;i < len;i++) {
                if(s[i] == '?') {
                    if(++cnt > num) s[i] = ')';
                    else s[i] = '(';
                }
                else continue;
            }
            for(int i = 0;i < len;i++) {
                if(s[i] == '(') st.push(s[i]);
                else if(s[i] == ')') {
                    if(st.empty()) {
                        flag = 0;
                        break;
                    }
                    else st.pop();
                }
            }
            if(flag == 0 || !st.empty()) cout << "NO" << endl;
            else cout << "YES" << endl;
        }
    }
    return 0;
}
           

B. Red and Blue

題解:

給出了兩個序列,讓我們不改變他們元素的相對順序的前提下合并兩個序列,新生成的序列

a

滿足: f ( a ) = m a x ( a 1 , a 1 + a 2 , . . . . . . , a 1 + a 2 + a 3 + . . . + a n + m ) f(a) = max(a_1,a_1 + a_2,......,a_1 + a_2 + a_3+...+a_{n + m}) f(a)=max(a1​,a1​+a2​,......,a1​+a2​+a3​+...+an+m​)

那麼可以直接維護兩個序列的字首和最大值,然後放在一起就OK了

AC代碼

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -1e12
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)

using namespace std;

const int maxn = 1e3 + 10;

int r[maxn],b[maxn];
int rm[maxn],bm[maxn];
int r_max,b_max;
int t,n,m;

void init()
{
    r_max = 0;
    b_max = 0;
    me(rm,0);
    me(bm,0);
    me(r,0);
    me(b,0);
}

int main()
{
    ios;
    cin >> t;
    while(t--) {
        init();
        cin >> n;
        for(int i = 1;i <= n;i++) cin >> r[i];
        cin >> m;
        for(int i = 1;i <= m;i++) cin >> b[i];
        for(int i = 1;i <= n;i++) {
            rm[i] = rm[i - 1] + r[i];
            r_max = max(r_max,rm[i]);
        }
        for(int i = 1;i <= m;i++) {
            bm[i] = bm[i - 1] + b[i];
            b_max = max(b_max,bm[i]);
        }
        cout << r_max + b_max << endl;
    }
    return 0;
}
           

C.Building a Fence

題解:

首先我們規定好每一個栅欄可以修築的最大高度,然後對于第一個栅欄他肯定是隻能在

h

的高度上,也就是說它的高度範圍會被限定在 [ l , r ] , l = r = h [l,r],l = r = h [l,r],l=r=h上,那麼我們再通過第一個栅欄的高度範圍去确定第二個栅欄的範圍:

他需要滿足的條件是:第二個栅欄距地面的懸浮高度不能大于 k − 1 k - 1 k−1,同時他和前一個栅欄的公共邊長至少是1,那麼我們已知每一個栅欄的高度都相同為

k

,那麼滿足題意的第二個栅欄的高度範圍是: [ l − ( k − 1 ) , r + ( k − 1 ) ] [l - (k - 1),r + (k - 1)] [l−(k−1),r+(k−1)]這個可以畫圖了解。其次我們還要注意到,它距離地面的高度至少0,最大是 k − 1 k - 1 k−1,那麼我們需要再去進行一次比對: l 2 = m a x ( l − ( k − 1 ) , n ) l_2 = max(l - (k - 1),n) l2​=max(l−(k−1),n), r 2 = m i n ( n , r + ( k − 1 ) ) r_2 = min(n,r + (k - 1)) r2​=min(n,r+(k−1))這樣子如果最後的結果是 l ⩽ r l \leqslant r l⩽r那就說明是可以滿足的,但是我們需要注意的一個點是:最後一個栅欄位置也是在地上,是以我們必須在處理最後一個栅欄的時候有一個特判,也就是說我們得出的這個 [ l , r ] [l,r] [l,r]的範圍必須包含了

h

,隻要最後判斷一下 r ⩽ n , l ⩾ n r \leqslant n , l \geqslant n r⩽n,l⩾n即可。

AC代碼:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -1e12
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)

using namespace std;

const int maxn = 2e5 + 10;

ll h[maxn];

int t,k,n;

int main()
{
    ios;
    cin >> t;
    while(t--) {
        cin >> n >> k;
        bool flag = 0;
        for(int i = 1;i <= n;i++) cin >> h[i];
        ll l = h[1],r = h[1];
        for(int i = 2;i <= n;i++) {
            ll t1 = l - (k - 1);
            ll t2 = r + (k - 1);
            t1 = max(t1,(ll)h[i]);
            t2 = min(t2,(ll)(h[i] + k - 1));
            if(t1 > t2) flag = 1;
            l = t1;r = t2;
        }
        if(flag || l > h[n] || r < h[n]) cout << "NO" << endl; //?
        else cout << "YES" << endl;
    }
    return 0;
}
           

D.Ceil Divisions

題解:

又是一道數學題

我們注意一下他說的這個 n + 5 n + 5 n+5是怎麼想的。

既然我們想讓這個序列中隻有一個2和 n − 1 n - 1 n−1個1,那麼我們首先想到的就是我們把現在序列裡有的這個1,2保持不動,這樣子我們隻需要去執行 n − 2 n - 2 n−2個數的操作,然後我們發現,隻要 x < y x < y x<y那麼最後得出的 a x = 1 a_x = 1 ax​=1這時候操作的步數是最小的,于是我們就發現,如果我們用所有的數去和

n

配對,那麼我們就可以在 n − 3 n - 3 n−3步内把除了

n

以外的數全部變成1。但是問題就是

n

要怎麼處理。

我們肯定想到的是用 n \sqrt{n} n

​來做,這樣最後我們隻需要兩步操作就可以讓

n

變為1,但是如果

n

本身不是一個完全平方數呢?那麼就讓 [ 2 , ( n − 1 ) ] [2,(n-1)] [2,(n−1)]中第一個平方大于他的數去和他配對,這樣子就一定可以在兩步之内實作換1,2e5的資料量最多進行5次開方就到2了,是以我們可以做的最多的變換次數就是 n − 2 + 5 = n + 3 < n + 5 n - 2 + 5 = n + 3 < n + 5 n−2+5=n+3<n+5是以我們這個思路是正确的。

AC代碼:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<bitset>
#include<list>
#include<set>
#include<limits.h>
#define ll long long
#define INF 0x3f3f3f3f
#define inf -1e12
#define me(a,b) memset(a,b,sizeof(a))
#define PII pair<int,int>
#define ull unsigned long long
#define ios std :: ios :: sync_with_stdio(false)

using namespace std;

const int maxn = 2e5 + 10;

ll t,n;

int main()
{
    ios;
    cin >> t;
    while(t--) {
        cin >> n;
        ll ans = n + 5; //我這裡直接用的n + 5其實也是一樣做的
        cout << ans << endl;
        for(ll i = n - 1;i > 1;i--) { //注意這裡要用long long 
            if((i - 1) * (i - 1) > n) {
                cout << i << ' ' << n << endl;
                ans --;
            }
            else if((i - 1) * (i - 1) <= n) {
                cout << n << ' ' << i << endl << n << ' ' << i << endl;
                n = i; //更換最大值
                ans -= 2; 
            }
        }
        while(ans > 0) {
            cout << 1 << ' ' << n << endl;
            ans --;
        }
    }
    return 0;
}
           

繼續閱讀