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,如果已经存在了某两个刻度之间距离为xy ,则答案为1,如果已经存在了某两个刻度之间距离为xy ,则答案为0
这个可以通过枚举刻度a[i] ,然后二分判断是否存在a[i]+xa[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]valval 时,让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;
}
发布了378 篇原创文章 · 获赞 10 · 访问量 32万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章