打得有点怂,这次div1题目比较水,我做了三题,不过比较坑的是,我第二题因为少了几个特判,wa了8次才ac,第三题因为看错题,wa了两次才ac
在正式和非正式选手里排名438名
在正式选手里排名306名
(做了三题,罚时太惨被一堆做2题的艹了。。。)
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;
}
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;
}
http://codeforces.com/contest/480/problem/C
一个 n 层摩天楼里,某个人初始在 a 层,每一步可以从一层 x 走到另一层 x′ ,但是有限制: |x−x′|<|x−b| ,且不能停留在原楼层不动,问这个人走 K 步,有多少种不同的走法
一个非常显然的DP思路: f[i][j]= 走完 i 步后,这个人在第 j 层的方案数。答案就是 ∑f[K][i]
设 dis=|x−b|−1 ,则 f[i][j] 可以转移到 f[i+1][max{1,j−dis}] 到 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;
}