Codeforces 每日一练 1067A+1267L+1217B

1067A Array Without Local Maximums

传送门
题意:给定一个数列,其中-1代表不确定,替换所有的-1,使得任意一项小于两侧的最大值,输出方案数。
一道1e5的三维dp,首先考虑dp的过程中需要表示哪些量——位置,当前位置的值,和前一个的关系。假设0/1/2分别代表大于/等于/小于,不难得出下列转移方程: d p [ i ] [ j ] [ 1 ] = d p [ i − 1 ] [ j ] [ 1 ] + d p [ i − 1 ] [ j ] [ 2 ] + d p [ i − 1 ] [ j ] [ 0 ] dp[i][j][1]=dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][0] dp[i][j][1]=dp[i1][j][1]+dp[i1][j][2]+dp[i1][j][0] d p [ i ] [ j ] [ 0 ] = ∑ m = 1 j − 1 ( d p [ i − 1 ] [ m ] [ 1 ] + d p [ i − 1 ] [ m ] [ 2 ] + d p [ i − 1 ] [ m ] [ 0 ] ) dp[i][j][0]=\sum_{m=1}^{j-1}(dp[i-1][m][1]+dp[i-1][m][2]+dp[i-1][m][0]) dp[i][j][0]=m=1j1(dp[i1][m][1]+dp[i1][m][2]+dp[i1][m][0]) d p [ i ] [ j ] [ 0 ] = ∑ m = j + 1 200 ( d p [ i − 1 ] [ m ] [ 1 ] + d p [ i − 1 ] [ m ] [ 2 ] ) dp[i][j][0]=\sum_{m=j+1}^{200}(dp[i-1][m][1]+dp[i-1][m][2]) dp[i][j][0]=m=j+1200(dp[i1][m][1]+dp[i1][m][2]) 关于初始化,我们只需要假设第0位是0就好

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
#define il inline
#define mod 998244353
#define int long long
int a[maxn],dp[maxn][210][3];
signed main() {
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    for (int i = 1; i <=n ; ++i) {
        cin>>a[i];
    }
    for (int i = 1; i <=200 ; ++i) {
        if(a[1]==-1||a[1]==i){
            dp[1][i][0]=1;
        }
    }
    for (int i = 2; i <=n ; ++i) {
        int sum=0;
        for (int j = 1; j <=200 ; ++j) {
            if(a[i]==-1||a[i]==j){
                dp[i][j][0]=sum;
                dp[i][j][1]=(dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][0])%mod;
            }
            sum=(sum+dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][0])%mod;
        }
        sum=0;
        for (int j = 200; j >=1 ; --j) {

            if(a[i]==-1||a[i]==j){
                dp[i][j][2]=sum;
            }sum=(sum+dp[i-1][j][1]+dp[i-1][j][2])%mod;
        }
    }
    ll sum=0;
    for (int i = 1; i <=200 ; ++i) {
        if(a[n]==-1||a[n]==i){
            sum=(sum+dp[n][i][1]+dp[n][i][2])%mod;
        }
    }
    cout<<sum;
    return 0;
}

1267L Lexicography

传送门
题意:一个长度n*l的字符串,将他分割成n个长度l字符串,使得按字典序从小到大排列时,第k个字符串的字典序尽可能小。
显然我们只需要考虑前k个就好,排序之后,第一次我们可以依次放进k个字符串,假设有m个和第k个相同,那么第二次放入字母时只需要考虑这m个就好,因为前k-m个肯定比第k个小。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1005
char ans[maxn][maxn];
int pos[maxn],cnt=1;int n, l, k;char s[maxn*maxn];
#define il inline
il void insert(int x,int a){
    memset(pos,0, sizeof(pos));
    for (int i = a; i <=k ; ++i) {
        if(!pos[s[cnt]]){
            pos[s[cnt]]=i;
        }
        ans[i][x]=s[cnt++];
    }
    if(x==l)return;
    insert(x+1,pos[ans[k][x]]);
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> l >> k;
    cin >> (s + 1);
    s[0] = 1;
    sort(s + 1, s + 1 + n * l);
    insert(1,1);
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=l ; ++j) {
            if(!ans[i][j])cout<<s[cnt++];
            else cout<<ans[i][j];
        }
        cout<<"\n";
    }
    return 0;
}

1217B Zmei Gorynich

传送门
题意:n个法术和一只x头龙,第i个可以使魔龙掉d[i]个头,长h[i]个头,询问最少多少次可以把龙打败。
贪心水题了,如果可以秒了巨龙就秒,如果秒不掉,输入时记录伤害的最大值和d,h差的最大值,如果差的最大值<=0,显然不能打败,否则就用最大差值使龙的头数减少至最大伤害可以秒杀的情况。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
#define il inline
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        ll n,x;
        cin>>n>>x;
        int fl=0;
        ll a=0,b=-10000000000;
        for (int i = 0; i <n ; ++i) {
            ll d,h;
            cin>>d>>h;
            a=max(a,d);
            b=max(b,d-h);
            if(b>=0&&d>=x)fl=1;
            if(d>=x)fl=1;
        }
        if(fl)cout<<1<<endl;
        else{
            if(b<=0)cout<<-1<<endl;
            else{
                x-=a;
                ll tmp;
                if(x%b==0){
                    tmp=1+x/b;
                }else{
                    tmp=2+x/b;
                }
                cout<<tmp<<endl;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以分享一种有效的训计划,以达到codeforces橙名。首先,建立一个长期的训计划,每周至少完成3-4个题目,把每个题目的解题过程都认真的思考一遍,确保理解每一步的思路。建议每隔一段时间,做一次综合习,以更好地检验自己的知识水平。此外,参加竞赛也可以加深对算法的理解,从而提升解题能力。 ### 回答2: 想要在Codeforces达到橙名的水平,需要进行系统性的训,并掌握一定的算法和编程技巧。以下是一个可能的训计划: 1. 学习基础知识:首先,建议你系统地学习计算机科学的基础知识,包括数据结构和算法。这可以帮助你理解不同问题的解决方案,并优化代码的执行效率。 2. 解决题目:开始刷题是锻炼算法和编码能力的关键。选择一些简单的题目,如Codeforces的Div2 A、B级题目,按难度逐渐增加。通过不断解决题目,你将熟悉各种算法,并提高编写清晰、高效代码的能力。 3. 学习算法:学习和掌握一些常用算法,如贪心、动态规划、图论等。理解算法原理,分析其时间和空间复杂度,并通过习将其应用于具体的问题。 4. 参加比赛:参加Codeforces的比赛是衡量自己水平的好方法。开始参加Div2级别的比赛,并争取在中等难度的题目上取得好成绩。逐渐挑战3级、4级比赛,尽量与更强的选手竞争,以提高自己的水平。 5. 反思和学习:每次比赛后,对自己的解题过程进行反思和总结。分析解错的原因,学习其他参赛选手的思考方式和技巧。通过学习他人的优秀代码和解题思路,不断提升自己的编码能力。 6. 习编码技巧:除了算法,熟掌握编码技巧也非常重要。学习并应用一些常用的数据结构和STL库,如数组、链表、栈、队列等。多写一些小项目或习题,锻炼自己的编码能力。 7. 时间管理:合理安排学习和习的时间。每天保持一定时间的刷题和学习,坚持养成好的学习习惯。同时,在比赛中也要控制好时间,并尽量在限定时间内完成题目。 总之,达到Codeforces橙名的水平需要长期的训和不断的学习。通过刷题、学习算法和编码技巧、参加比赛以及反思总结,你可以逐渐提升自己的水平,并取得理想的成绩。记住,坚持和持续学习是达到目标的关键。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值