AtCoder Beginner Contest 331(A~D)

感觉和cf div3差不多。

A - Tomorrow

签到,D和M是一年有D月M天,输入ymd输出ym[d+1],如果d+1>D了显然要m++,模拟即可。

#include <bits/stdc++.h>
//#define int long long
#define fr first
#define se second
#define endl '\n'
using namespace std;

int M,D,y,m,d;

void solve(){
    cin>>M>>D>>y>>m>>d;
    d++;
    while(d>D)d-=D,m++;
    while(m>M)m-=M,y++;
    cout<<y<<" "<<m<<" "<<d<<endl;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

B - Buy One Carton of Milk

题目大意:6个蛋S元,8个蛋M元,12个蛋L元,花最少的钱买到至少N个蛋,输出最少的钱。

范围给的很小,搜索一下就ok

#include <bits/stdc++.h>
//#define int long long
#define fr first
#define se second
#define endl '\n'
using namespace std;

int n,s,m,l,ans=INT_MAX;

void dfs(int a,int b,int c,int cost,int cnt){
    if(cost>=ans)return;
    if(cnt>=n){
        ans=min(ans,cost);
        return ;
    }
    dfs(a+1,b,c,cost+s,cnt+6);
    dfs(a,b+1,c,cost+m,cnt+8);
    dfs(a,b,c+1,cost+l,cnt+12);
}

void solve(){
    cin>>n>>s>>m>>l;
    //6个蛋s元,8个蛋m元,12个蛋l元
    //花最少的钱买到至少n个蛋
    dfs(0,0,0,0,0);
    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

C - Sum of Numbers Greater Than Me

题目大意:给你一个序列A,对于A1,输出A2~An中大于A1的和,其他的类推。

序列范围大小1e5,两个for过不了,发现序列的值小于1e6,开另一个数组差分优化。

数x可以对1~x-1产生贡献x,那么b[1]+=x,b[x]-=x,最后遍历一遍输出。

#include <bits/stdc++.h>
#define int long long
#define fr first
#define se second
#define endl '\n'
using namespace std;

const int N=2e5+5,A=1e6+5;
int n,a[N],b[A];
map<int,int>f;

//b[i]=j,代表比i大的数之和为j

void solve(){
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        b[1]+=a[i],b[a[i]]-=a[i];
    }
    for(int i=1,t=0;i<=A;++i){
        t+=b[i];
        f[i]=t;
    }
    for(int i=1;i<=n;++i)
        cout<<f[a[i]]<<" ";
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

补题:D - Tile Pattern

感觉是二维分块,左上角到右下角有几个完整块先算出来,剩下的小块for跑一遍。

vp的时候没做,直接跳过了(做不来)过会补。

upd:2023-12-6

都不用分块标号,画图出来之后就是有规律的。(图就搬洛谷的了)

黄色是完整块,黄色和蓝色和紫色是不完整块,根据图找一下下标规律就可以了。

#include <bits/stdc++.h>
#define int long long
#define fr first
#define se second
#define endl '\n'
using namespace std;

const int N=1e3+5;
int n,q,a[N][N],f[N][N],cnt;
string s[N];

int getb(int x,int y){
    int res=(x/n)*(y/n)*cnt;//完整块
    res+=f[x%n][y%n];//紫块
    res+=(x/n)*f[n][y%n];//绿块
    res+=(y/n)*f[x%n][n];//蓝块
    return res;
}

int query(){
    int a,b,c,d,res;
    cin>>a>>b>>c>>d;
    a++,b++,c++,d++;//下标均+1
    res=getb(c,d);
    res-=getb(c,b-1);
    res-=getb(a-1,d);
    res+=getb(a-1,b-1);
    return res;
}

void solve(){
    cin>>n>>q;
    for(int i=0;i<n;++i)cin>>s[i];
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            a[i+1][j+1]=s[i][j]=='B'?1:0,
            cnt+=a[i+1][j+1];

    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)//二维前缀和
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];

    for(int i=1;i<=q;++i)cout<<query()<<endl;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

E - Set Meal 

题目大意:给你序列A,序列B,在序列A中选一个x,B中选一个y,要求x+y最大,同时x和y没有被禁止。

两个for跑一遍直接爆了,因为要最大的可以把B升序排序(注意保留原来下标顺序)。

直接逆序遍历B找到可以配对的更新一下答案,然后break。

因为最多有L个被禁止配对,所以看起来是两重for,实际上两重循环复杂度是L。

// LUOGU_RID: 138251069
#include <bits/stdc++.h>
//#define int long long
#define fr first
#define se second
#define endl '\n'
using namespace std;

const int N=1e5+5;
int n,m,l,ans=INT_MIN;
map<pair<int,int>,bool>f;//不提供的
struct Node{
    int idx,val;
}a[N],b[N];

bool cmp(Node a,Node b){
    return a.val<b.val;
}

void solve(){
    cin>>n>>m>>l;
    for(int i=1;i<=n;++i){
        cin>>a[i].val;
        a[i].idx=i;
    }
    for(int i=1;i<=m;++i){
        cin>>b[i].val;
        b[i].idx=i;
    }
    for(int i=1,A,B;i<=l;++i){
        cin>>A>>B;
        f[{A,B}]=true;
    }

    sort(b+1,b+1+m,cmp);

    for(int i=1;i<=n;++i){
        for(int j=m;j>=1;--j){
            if(!f[{i,b[j].idx}]){
                ans=max(ans,a[i].val+b[j].val);
                break;
            }
        }
    }
    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

总结

就D题,不会可以先画图,不要空想。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值