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;
}