反思:赛时过两题,出题很慢,c题二分还不是很熟练,浪费了一点时间,做题顺序的选择比较随意,已经浪费了一个小时之后才开始看过题数多的题,但是好在敢于尝试,打字速度是我的痛啊。
a.Sierpinski carpet - SMUOJ
思路:由于第i个图总与第i-1个图像相关,并且,n<=6范围很小,于是可以使用递归,容易漏掉n=0时的情况。
代码:
#include<bits/stdc++.h>
#define int long long
int a[1000100];
char b[1000][1000];
using namespace std;
int L,n,m;
void setp(int x){
int tt =pow(3,x);
int ttt =pow(3,x-1);
if(x==1){
for(int i=1;i<=tt;i++){
for(int j=1;j<=tt;j++){
if(i>tt/3&&i<=(tt/3)*2&&j>tt/3&&j<=(tt/3)*2) b[i][j]='.';
else if(i%3==j%3&&i%3==2&&j%3==2) b[i][j]='.';
else b[i][j]='#';
}
}
}
else{
char c[1000][1000];
memcpy(c,b,sizeof b);
for(int i=1;i<=tt;i++){
for(int j=1;j<=tt;j++){
if(i>tt/3&&i<=(tt/3)*2&&j>tt/3&&j<=(tt/3)*2) b[i][j]='.';
else {
int k1=i%ttt;int k2=j%ttt;
if(i%ttt==0) k1=ttt;
if(j%ttt==0) k2=ttt;
b[i][j]=c[k1][k2];
}
}
}
}
// cout<<" )"<<endl;
}
void solve(){
cin>>n;
int tt=pow(3,n);
int p=1;
while(p<=n){
setp(p);
p++;
}
if(n==0) cout<<"#"<<endl;
else
for(int i=1;i<=tt;i++){
for(int j=1;j<=tt;j++){
cout<<b[i][j];
}
cout<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}
b.Consecutive - SMUOJ
思路:l=a[y-1]-a[x-1]即可找到答案。
代码:
#define int long long
int a[1000100];
using namespace std;
int L,n,m;
int l=0,r,mid;
int sum;
int ans[1000100];
bool com(int x,int y){
return x>y;
}
void solve(){
cin>>n>>m;
string b;
cin>>b;
memset(ans ,1 ,sizeof ans);
for(int i=0;i<n;i++){
if(b[i]==b[i+1]) ans[i+1]=ans[i]+1;
}
l=0;
for(int i=0;i<n;i++){
if(ans[i+1]>=ans[i])
l+=ans[i+1]-ans[i];
a[i+1]=l;
}
while(m--){
int x,y;
cin>>x>>y;
l=a[y-1]-a[x-1];
cout<<l<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}
c.Minimum Width - SMUOJ
思路:这个题虽然是赛时过的,但由于是二分不是很熟悉·,在这里讲讲思路,由于要找的是最小长度,如果mid不满足条件,就在左范围找,
代码:
#include<bits/stdc++.h>
#define int long long
int a[1000100];
int b[1000100];
using namespace std;
int L,n,m;
int l=0,r,mid;
bool check(int num){
int w=1,sum=-1;
for(int i=1;i<=n;i++){
if(sum+1+a[i]<=num){
sum=sum+1+a[i];
}else{
sum=a[i];
w++;
}
}
if(sum==-1){
w--;
}
if(w<=m){
return true;
}
return false;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++) { cin >> a[i];r+=a[i];l=max(l,a[i]);}
int ans=0;
l-=1;
r+=n+1;
// cout<<l<<r<<endl;
while(l+1<r){
mid=(l+r)/2;
// cout<<l<<" "<<r<< " "<<mid<<check(mid)<<endl;
// cout<<mid<<endl;
if(!check(mid)){
l=mid;
}
else { r = mid ; }
}
cout<<r<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}
d.Printing Machine - SMUOJ
思路:贪心,打印一次后,需要充电一微秒后才能再次打印就可以看作每微妙只能打印一个产品。然后就可以这个题看作一个贪心的过程,我们一定是要每次打印已经进入了打印机的产品中最快退出打印机的产品。 因为打印它后,你还可以继续打印哪些没有退出打印机的产品,如果先打印后退出的,可能会导致部分产品还没有打印就已经退出。 (这里遍历时,如果遇到能加入打印机的产品,也就产品加入打印机)。如果整个打印机中没有产品,我们就将时间调整到下一个最快能进入打印机的时刻,这样就可以快速遍历时间。
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;
const int N = 2e5 + 10;
int n;
vector<PII> a; // 存放数据,第一个数放入进来时间,第二个出去时间
int main()
{
cin >> n;
for(int i = 0; i < n; i ++ )
{
ll t, d;
cin >> t >> d;
a.emplace_back(t, t + d);
}
sort(a.begin(), a.end());
priority_queue<ll, vector<ll>, greater<ll>> q; // 小根堆
ll idx = 0, res = 0; // idx 数组a下标, res 结果
for(ll i = 0; ; i ++ ) // 每一个时间点都只能放入一个,故i++ 表示时间推移
{
if(q.empty()) // 为空,直接跳过这一大段时间
{
if(idx == n) break; // 每个点都考虑到了,退出
i = a[idx].first; // 时间跃迁
}
/* 将可以在i秒开始打印的东西的结束时间放进队列中,等待打印(这些东西打印的起始时间可能不同) */
while(idx < n && a[idx].first == i) q.push(a[idx ++ ].second);
/* 如果队列不空,且堆顶的值已经过了可以工作的时间,则这个点可以删掉,不必考虑 */
while(!q.empty() && q.top() < i) q.pop();
/* 如果堆有东西,则说明可以i这个点可以工作 */
if(q.size())
{
q.pop(); // 工作完之后就可以爬开了
res ++ ; // 工作量++
}
}
cout << res << endl;
return 0;
}
e.Nearest Black Vertex - SMUOJ
思路:待补充
f.Christmas Present 2 - SMUOJ
思路:待补充