寒假思维训练计划day2

Day2(贪心 + 构造 2024-01-06):Problem - 1904D1 - Codeforces

题意:
给定两个长度为n的数组,可以对a数组进行操作:
选定l <= r, a[l], a[l + 1], .. a[r] := max(a[l], a[l + 1], ..., a[r]) 
使得最后的b==a
题解:这道题是小数据范围
首先,小元素对大元素是不会有任何的影响的,所以我们不妨从小元素开始,然后分块看,每个块l到r的b值相同。

然后从较小者开始,为什么这样子贪心呢?首先是比它小的元素不会对他有影响,它的变化不会影响到比他大的块,同时考虑标记已经处理好的块, 这个数据范围直接暴力枚举最靠近左边界的和右边界的a[i]==b[l..r]的点,特判一下之间的点,注意判断最大值即可。
C++代码:

这个代码比较长,建议只看solve()部分,就是在暴力,主要是理解为什么是这个处理的顺序。

#include  
#define int long long 
#define ff first 
#define ss second 
#define pb push_back 
using namespace std; 
using PII = pair; 
const int N = 1010, inf = 0x3f3f3f3f; 
int n, m, cnt; 
int a[N], b[N];
bool st[N];
void solve(int o) {
    cin >> n; 
    for(int i = 1; i <= n; i ++ ) cin >> a[i]; 
    for(int i = 1; i <= n; i ++ ) cin >> b[i], st[i] = 0;  
    vector us[n + 2];  
    for(int i = 1; i <= n; i ++ ) {
        int j = i; 
        while(j + 1 <= n && b[j + 1] == b[i]) ++ j;
        us[b[i]].pb({i,j});
        i = j;
    }
    bool flag = 1;
    for(int bkv = 1; bkv <= n; bkv ++ ) {
        if(!us[bkv].size()) continue;
        for(auto t : us[bkv]) {
            int l = t.ff, r = t.ss, mx = a[l], idx;
            for(int i = l; i <= r; i ++ ) mx = max(mx, a[i]);
            if(mx > b[l]) {
                flag = 0; 
                break;
            }
            if(mx == b[l]) {
                for(int i = l; i <= r; i ++ ) a[i] = b[l],st[i] = 1; 
                continue;
            }
            mx = a[l], idx = l;
            for(int i = l; i >= 1; i -- )
                if(a[i] <= b[l] && !st[i]) mx = max(a[i],mx),idx = i;
                else break; 
            if(mx == b[l]) {
                for(int c = idx; c <= r; c ++ ) {
                    a[c] = b[l]; 
                    if(c >= l && c <= r) st[c] = 1; 
                }
                continue;
            }
            mx = a[r], idx = r;
            for(int i = r; i <= n; i ++ )
                if(a[i] <= b[l] && !st[i]) mx = max(a[i],mx),idx = i;
                else break; 
            if(mx == b[l]) {
                for(int c = l; c <= idx; c ++ ) {
                    a[c] = b[l]; 
                    if(c >= l && c <= r) st[c] = 1; 
                }
                continue;
            }
            flag = 0; 
            break;
        }
        if(!flag) break;
    }
    if(flag) cout << "YES" << endl; 
    else cout << "NO" << endl; 
}
signed main() {
    ios::sync_with_stdio(false); 
    cin.tie(0); 
    cout.tie(0);
    int ts; 
    cin >> ts; 
    for(int o = 1; o <= ts; o ++ ) {
        solve(o);
    }   
    return 0; 
}

你可能感兴趣的:(算法)