SMU Summer 2024 Contest Round 2

SMU Summer 2024 Contest Round 2

2024.7.9 9:00————11:00

过题数3/6
补题数4/6

  • Sierpinski carpet
  • Consecutive
  • Minimum Width
  • Printing Machine
  • Nearest Black Vertex
  • Christmas Present 2

A - Sierpinski carpet

题解:
给出数字k,每9个循环,中间镂空,具体输出见示例。
本来想直接暴力k的,0——6,3的六次方有点太大了,可以循环每个即可,一个比较简单的模拟。特别注意不要忘记n=0。
代码:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    char a[730][730];
    memset(a,'#',sizeof a);
        for (int i = 1; i < 3; i++) {
            for (int j = 1; j < 3; j++) {
                a[i][j] = a[i%3][j%3];
                if (i >= 1 && i < 2*1 && j >= 1 && j < 2*1) {
                    a[i][j] = '.';
                }
            }
        }
    int nn = n;
    for (n = 2; n <= 6; n++){
        for (int i = 1; i < pow(3,n); i++) {
            for (int j = 1; j < pow(3,n); j++) {
                if (i >= pow(3,n-1) || j >= pow(3,n-1)) {
                    int p = pow(3,n-1);
                    a[i][j] = a[i%p][j%p];
                    if (i >= pow(3,n-1) && i < 2*pow(3,n-1) && j >= pow(3,n-1) && j < 2*pow(3,n-1)) {
                        a[i][j] = '.';
                    }
                }
            }
        }
    }
    for (int i = 0; i < pow(3,nn); i++) {
        for (int j = 0; j < pow(3,nn); j++) {
            cout << a[i][j];
        }
        cout << endl;
    }
    return 0;
}

B - Consecutive

题解:
给定长度为n的字符串s,q个询问,求在l到r的范围内有多少组俩个连续字符。
前缀和,简单题,直接上代码。
代码:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n,q;
    cin >> n >> q;
    string s;
    cin >> s;
    int sm[300005];
    sm[0] = 0;
    for (int i = 1; i < n; i++) {
        if (s[i] == s[i - 1]) {
            sm[i] = sm[i-1]+1;
        }
        else sm[i] = sm[i-1];
    }
    while (q--) {
        int l,r;
        cin >> l >> r;
        l--;
        r--;
        cout << sm[r] - sm[l] << endl;
    }
    return 0;
}

C - Minimum Width

巧了昨天刚学过二分,wa了一次改了一下判断条件就过了。
题解:
n个长度为l【i】的单词,每个单词间隔一空,行首不用间隔,给定最多m行,求窗口最小宽度。
二分并判断即可。
代码:

#include<bits/stdc++.h>
using namespace std;

int n,m;
long long L[200005];
long long sum;

bool solve(long long x) {
    long long t = 0;
    long long ls = 0;
    for (int i = 0; i < n; i++) {
        if (t == 0) ls++;
        t += L[i];
        if (t < x) {
            t++;
        }
        else if (t == x) {
            t = 0;
        }
        else if (t > x) {
            t = L[i]+1;
            //t直接定在下一个单词开头
            ls++;
        }
    }
    if (ls <= m)return true;
    else return false;
}

int main() {
    cin >> n >> m;
    sum = n;
    long long ma = 0;
    for (int i = 0; i < n; i++) {
        cin >> L[i];
        sum += L[i];
        if (L[i] > ma) ma = L[i];
    }
    long long l = ma,r = sum;
    while (l < r) {
        long long mid = (l+r)/2;
        if (solve(mid)) {
            r = mid;
        }
        else l = mid+1;
    }
    cout << r << endl;
    return 0;
}

D - Printing Machine

对着这题目和题解得有将近四小时吧,看的还是很懵而且对着答案一直在改,给我改麻木了已经。
题解:
N个产品,每个产品在T【i】时间持续D【i】秒经过打印机,可以接受打印,打印是一瞬间的事但打印完需要冷却一秒。
一个比较典型的贪心,要用到优先队列小顶堆,具体见注释。
代码:

#include<bits/stdc++.h>
using namespace std;

#define int long long
int n;
long long t[200005];
long long d[200005];
long long p[200005];

signed main() {
    cin >> n;
    vector<pair<int,int>>mp(n);
    for (auto &[l, r]: mp)
        cin >> l >> r, r += l;
    sort(mp.begin(),mp.end());
    //会先根据first,再second排序
    
//    for (int i = 0; i < n; i++) {
//        cout << mp[i].first << ' ' << mp[i].second << endl;
//    }
    
    priority_queue<int, vector<int>,greater<>>q;
    //小顶堆优先队列,储存所有可打印节点的右端点
    
    long long t = -1;
    long long ans = 0;
    for (int i = 0; i < n || !q.empty();) {
        if (q.empty() && i < n) {
            q.push(mp[i].second);
            t = mp[i].first;
            //直接作为当前时间即可
            i++;
        }//所有此前的都完毕,当前产品进入
        while (i < n && mp[i].first <= t) {
            q.push(mp[i].second);
            i++;
            //下一个!
        }//所有在当前时间以前的都进去
        if(!q.empty()) {
            if (t <= q.top()){
                ans++;
                t++;
            }
            //在它走之前赶紧把最小的打印了
            q.pop();
        }//能运行就运行一个,不能也得走了
    }
    cout << ans << endl;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值