Codeforces #274 Div 1 简要题解

比赛总结

打得有点怂,这次div1题目比较水,我做了三题,不过比较坑的是,我第二题因为少了几个特判,wa了8次才ac,第三题因为看错题,wa了两次才ac
在正式和非正式选手里排名438名
在正式选手里排名306名
(做了三题,罚时太惨被一堆做2题的艹了。。。)

A. Exams

题目链接

http://codeforces.com/contest/480/problem/A

题目大意

某人要参加 n 场考试,第i场考试是在第 ai 天考,也可以提前放到第 bi 天考,但是提前考试的话,登分会标记这次考试是在第 ai 天考的。考完一次考试登记一次考试时间。他希望登记册里,登记的时间是非降的,问最后一场考试最早能在什么时候进行

思路

考试进行的顺序,一定是按照 ai 升序,即先考 ai 小的,再考 ai 大的。

但是每场考试是选 ai 天考还是 bi 天考呢?显然是尽量选 bi 天考,我们记录 last= 上一次考试的日期,若 bi>=last ,就选 bi 天考,否则就只能选 ai 天考了。由于 bi<ai ,而且之前预处理时,考试是按照 ai 为第一关键字升序, bi 为第二关键字升序,所以 ai 保证是大于等于 last 的。这样的做法是一定正确的

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 6000

using namespace std;

pair<int,int>pr[MAXN];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&pr[i].first,&pr[i].second);
    sort(pr+1,pr+n+1);
    int last=pr[1].second;
    for(int i=2;i<=n;i++)
    {
        if(pr[i].second>=last) last=pr[i].second;
        else last=pr[i].first;
    }
    printf("%d\n",last);
    return 0;
}

B. Long Jumps

题目链接

http://codeforces.com/contest/480/problem/B

题目大意

给你一个长度为 L 、有n个刻度的尺子,第1号刻度是0,第 n 号刻度是L,给你每个刻度的位置,问最少要加多少个刻度,才能存在某两个刻度之间距离为 x ,某两个刻度之间距离为y

思路

显然,答案最多为2,如果已经存在了某两个刻度之间距离为 x y,则答案为1,如果已经存在了某两个刻度之间距离为 x y,则答案为0
这个可以通过枚举刻度 a[i] ,然后二分判断是否存在 a[i]+x a[i]+y 来解决

但是重点不在于此,而是一个特殊情况:有可能存在某两个已经存在的刻度,插入一个新的刻度后,就可以满足题目要求了。这个就需要特判了,具体看代码比较清楚吧

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 6000

using namespace std;

pair<int,int>pr[MAXN];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&pr[i].first,&pr[i].second);
    sort(pr+1,pr+n+1);
    int last=pr[1].second;
    for(int i=2;i<=n;i++)
    {
        if(pr[i].second>=last) last=pr[i].second;
        else last=pr[i].first;
    }
    printf("%d\n",last);
    return 0;
}

C. Riding in a Lift

题目链接

http://codeforces.com/contest/480/problem/C

题目大意

一个 n 层摩天楼里,某个人初始在a层,每一步可以从一层 x 走到另一层x,但是有限制: |xx|<|xb| 且不能停留在原楼层不动,问这个人走 K 步,有多少种不同的走法

思路

一个非常显然的DP思路:f[i][j]=走完 i 步后,这个人在第j层的方案数。答案就是 f[K][i]

dis=|xb|1 ,则 f[i][j] 可以转移到 f[i+1][max{1,jdis}] f[i+1][min{n,j+dis}] ( f[i+1][j] 除外!)

这样DP的复杂度为 O(n3) ,可以考虑通过优化贡献答案的那部分来降维。

我们知道,给一个序列不断进行区间加的操作,可以维护一个数组a[] a[] ,每次区间[L,R] [L,R] val val 时,让 a[L]+=val , a[R+1]+=val ,最后通过求前缀和即可得到若干次操作后的序列,这样操作,每次是 O(1) 的,就能在DP的区间更新答案步骤里做到降维了,每次枚举完某个 i 的所有f[i][]后,再通过求 f[i][] 的前缀和来还原dp数组

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 6000

using namespace std;

pair<int,int>pr[MAXN];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&pr[i].first,&pr[i].second);
    sort(pr+1,pr+n+1);
    int last=pr[1].second;
    for(int i=2;i<=n;i++)
    {
        if(pr[i].second>=last) last=pr[i].second;
        else last=pr[i].first;
    }
    printf("%d\n",last);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值