Codeforces Round #336 div2
通过数:3(1题未来得及交)
Standing: 418
题目链接:
http://codeforces.com/contest/608
A:
到一个楼层的时候,如果有人,则更新ans = Max(ans, 此人等待时间)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1000 + 5;
int n, s;
struct D
{
int f, t;
}d[MAXN];
bool cmp(D a, D b){return a.f < b.f;}
int main()
{
while(scanf("%d%d", &n, &s) != EOF){
for(int i = 1 ; i <= n ; i++) scanf("%d%d", &d[i].f, &d[i].t);
int pre = s;
int ans = 0;
sort(d + 1 , d + 1 + n, cmp);
for(int i = n ; i >= 1 ; i--){
ans += pre - d[i].f;
if(ans < d[i].t) ans = d[i].t;
pre = d[i].f;
}
printf("%d\n", ans);
}
return 0;
}
B:
额,用了一种比较麻烦的写法。对b串统计一下每个位能在a中哪些位进行了使用。因为是一个连续区间段,所以用前缀和的方法处理就好。
更好的一种写法是统计a中每个位在b中哪些位置进行了使用,可以减少一个数组,也相对好处理一些。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
using namespace std;
const int MAXN = 200000 + 5;
char a[MAXN], b[MAXN];
long long a1[2][MAXN];
int main()
{
while(scanf("%s %s", a, b) != EOF){
int n = strlen(a);
int m = strlen(b);
a1[0][0] = a[0] == '0' ? 1 : 0;
a1[1][0] = a[0] == '0' ? 0 : 1;
for(int i = 1 ; i < n ; i++){
a1[0][i] = a1[0][i - 1], a1[1][i] = a1[1][i - 1];
if(a[i] == '0') a1[0][i]++;
else a1[1][i]++;
}
long long ans = 0;
for(int j = 0 ; j < m ; j++){
int mark = b[j] == '0' ? 1 : 0;
int le = max(n - m + j, 0);
int re = min(n - 1, j);
ans += a1[mark][re];
if(le != 0) ans -= a1[mark][le - 1];
}
printf("%I64d\n", ans);
}
return 0;
}
C:
因为加在最后的点攻击范围不确定,所以答案就相当于枚举每个点作为最后一个点的时候,能存活下来的点。
现场采用了一种二分的写法。假设当前点存活,二分在前面查找一个最近且不会被攻击到的点。
然而又有一种更优的写法。因为位置<=1e5,所以直接每个位置存信息就可以。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 100000 + 5;
struct D
{
int u, v;
}d[MAXN], e[MAXN];
bool cmp(D a, D b){return a.u < b.u;}
int dp[MAXN];
int main()
{
int n;
while(scanf("%d", &n) != EOF){
d[0].u = 0;
for(int i = 1 ; i <= n ; i++) scanf("%d%d", &d[i].u, &d[i].v);
sort(d + 1, d + n + 1, cmp);
dp[0] = 0;
int ans = n;
for(int i = 1 ; i <= n ; i++){
dp[i] = 1;
if(i == 1) continue;
int val = d[i].u - d[i].v;
val = max(val, 0);
int le = 0, re = i - 1;
while(le < re - 1){
int mid = (le + re) >> 1;
if(d[mid].u < val) le = mid;
else re = mid;
}
int mark;
if(d[re].u < val) mark = re;
else mark = le;
dp[i] += dp[mark];
// printf("ans[%d] = %d, mark = %d\n", i, dp[i], mark);
}
for(int i = 1 ; i <= n ; i++) ans = min(ans, n - dp[i]);
printf("%d\n", ans);
}
return 0;
}
D:
区间DP
dp[i][i] = 1,
Dp[i][i+1] = a[i] == a[i+1] ? 1 : 2,
Dp[i][j] = min{dp[i][k] + dp[k + 1][j]}
如果a[i] == a[j],dp[i][j] = min{dp[i][j], dp[i+1][j-1]}
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define inf (1000000007)
const int MAXN = 500 + 5;
int dp[MAXN][MAXN];
int a[MAXN];
int main()
{
int n;
while(scanf("%d", &n) != EOF){
for(int i = 1 ; i <= n ; i++) for(int j = 1 ; j <= n ; j++) dp[i][j] = inf;
for(int i = 1 ; i <= n ; i++) scanf("%d", &a[i]), dp[i][i] = 1;
for(int i = 1 ; i < n ; i++){
if(a[i] == a[i + 1]) dp[i][i + 1] = 1;
else dp[i][i + 1] = 2;
}
for(int i = 2 ; i <= n ; i++){
for(int j = 1 ; j + i <= n ; j++){
if(a[j] == a[j + i])
dp[j][j + i] = dp[j + 1][j + i - 1];
// else{
dp[j][j + i] = min(dp[j][j + i], dp[j + 1][j + i] + 1);
dp[j][j + i] = min(dp[j][j + i], dp[j][j + i - 1] + 1);
for(int k = j + 1 ; k < j + i ; k++){
int temp = dp[j][k] + dp[k + 1][j + i];
dp[j][j + i] = min(dp[j][j + i], temp);
// }
}
}
}
// for(int i = 1 ; i <= n ; i++){
// for(int j = 1 ; j <= n ; j++) printf("%d ", dp[i][j]);
// printf("\n");
// }
printf("%d\n", dp[1][n]);
}
return 0;
}