雅礼集训三十天,day7

发布时间 2023-09-24 16:02:46作者: libohan0518

总结

呃呃(考的最糟糕的一次!!)
0 + 100 + 0 + 0 = 100分
第三题用成了dp,第四题重载运算符写寄了!!!

总之WSSB

T1

这题要我们让 \(s\) 的数量最大化,那我们可以试试贪心,我们让 \(k\) 个为一组来考虑,后面只需要乘上 \(n \div k\),在考虑一下最后无法分组的几个数,那么如何填这 \(k\) 个数呢?
如果当前的前k天加起来的数加 \(s\) 小于 \(0\),则这个数选 \(s\),要不然选 \(d\),然后就没了(呃呃呃所以我说我是个kun

谢谢yabnto大奆佬提供的思路!!!!!!!!!!

code:
时间复杂度:\(O(t \cdot k)\)
空间复杂度:\(O(n)\)

#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e4 + 5;

int a[N], t, n, k, s, d; 

void Solve(){
    cin >> n >> k >> s >> d;  
    d *= -1;
    int sum = 0;
    for(int i = 1; i <= k; i++){
        if(sum + s + d * (k - i) < 0){
            a[i] = s;
        }        
        else a[i] = d;
        sum += a[i];
    }  
    sum *= n / k;
    for(int i = 1; i <= n % k; i++){
        sum += a[i];
    }
    if(sum >= 0){
        cout << sum;
    }
    else cout << "Deficit";
    cout << "\n";
}

signed main(){
    cin >> t;
    while(t--){
        Solve();
    } 
    return 0;
} 

T2

啊啊啊,就是一个二维前缀和好吧,没啥好说的!!
code:
时间复杂度:\(O(n ^ 2)\)
空间复杂度:\(O(n ^ 2)\)

#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e3 + 5;

int n, m, r, c, a[N][N], sum[N][N], ans;

int val(int x, int y, int i, int j){
    return sum[i][j] - sum[i][y - 1] - sum[x - 1][j] + sum[x - 1][y - 1];            
}

signed main(){
    freopen("matrix.in", "r", stdin);
    freopen("matrix.out", "w", stdout);
    cin >> n >> m >> r >> c;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            cin >> a[i][j];
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            int x = i - r + 1, y = j - c + 1;
            if(x <= 0 || y <= 0){
                continue;
            }
            ans = max(ans, val(x, y, i, j));
        }
    }
    cout << ans;
    return 0;
} 

T3

啊啊啊,我之前用的是 \(dp\),但是根据 \(Mr.Gengar\) (就是蒹葭) 的解释是说 \(dp\) 在这题会陷入局部最优解的循环中(虽然我没能听懂

然后我就想到了用二分来逼近 \(m\),然后对了!!
我们可以考虑一下先用 \(n ^ 2\) 处理出所有 \(p_i + p_j\) 存在 \(b_i\) 中(注意也可以不打,相当于在 \(p_i\) 中加一个为 \(0\) 的元素),然后枚举每一个 \(b_i\) 用二分找到一个 \(b_j\) 使得 \(b_i + b_j \leq m\) 然后取个最大值即可(注意如果 \(b_i > m\) 直接跳过)
code:
时间复杂度:\(O(n ^ 2 \cdot \log^2 n)\)
空间复杂度:\(O(n ^ 2)\)

#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e3 + 5;

int n, m, p[N], b[N * N], cnt, ans;

bool cmp(int x, int y){
    return x > y;
}

signed main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> p[i];
    }
    for(int i = 0; i <= n; i++){
        for(int j = 0; j <= n; j++){
            b[++cnt] = p[i] + p[j];
        }
    } 
    sort(b + 1, b + cnt + 1);
    for(int i = 1; i <= cnt; i++){
        if(b[i] > m){
            continue;
        }
        int tmp = upper_bound(b + 1, b + cnt + 1, m - b[i]) - b - 1;
        if(b[i] + b[tmp] <= m){
            ans = max(ans, b[i] + b[tmp]);
        }
    }
    cout << ans;
    return 0;
} 

T4

这题是独立想出来的(但是错的很傻逼
我们可以考虑把 \(a_i\)\(b_i\) 都排序,然后从 \([1, 1]\) 输出,没输出一个,就往优先队列里扔一个 \([i + 1, j]\)\([i, j + 1]\),然后再用一个 \(map\) 来去重即可
code:
时间复杂度:\(O(n \cdot \log n)\)
空间复杂度:\(O(n)\)

#include<bits/stdc++.h> 

using namespace std;

#define int long long

const int N = 1e5 + 5;

int n, a[N], b[N], cnt;

struct node{
    int x, y;
    bool operator < (const node &p) const{
        return a[x] + b[y] > a[p.x] + b[p.y];
    }
}cur;

priority_queue<node> q;
map<pair<int, int>, int> mp;

signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    } 
    for(int i = 1; i <= n; i++){
        cin >> b[i];
    }
    sort(a + 1, a + n + 1);
    sort(b + 1, b + n + 1);
    q.push({1, 1});
    for(int i = 1; cnt < n; i++){
        cur = q.top();
        q.pop();
        if(mp[{cur.x, cur.y}] > 0){
            continue;
        }
        cout << a[cur.x] + b[cur.y] << " ";
        cnt += 1;
        mp[{cur.x, cur.y}] += 1;
        q.push({cur.x + 1, cur.y});
        q.push({cur.x, cur.y + 1});
    } 
    return 0;
}