C130【?XXXX级】0321 ?组测试
欢迎到学校的OJ去切题QWQ
他妈的,来DP全家桶是吧
Problem A
非常的Simple啊。
我们考虑\(dp_i\)为当前到第\(i\)个数的时候能得到的最大值。
\(dp_i=max(dp_{i-1},dp_{i-2}+a_i)\)
要么我们选不了当前这个数,沿用上一个数的时候的最大值;要么就更新。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int dp[N], a[N];
int n, t;
int read()
{
int x = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * w;
}
void clear()
{
memset(dp, 0, sizeof dp);
n = 0;
}
void solve()
{
clear();
n = read();
for (int i = 1; i <= n; i++)
a[i] = read();
dp[1] = a[1], dp[2] = max(a[1], a[2]);
for (int i = 3; i <= n; i++)
dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);
printf("%d\n", dp[n]);
}
int main()
{
t = read();
while (t--)
solve();
return 0;
}
Problem B
很搞笑啊。为什么不尊重原题把原题目给复制过来啊?非得自己改一个名字,这台麻烦哦了
链接:https://ac.nowcoder.com/acm/contest/11171/B
来源:牛客网
设dp[i, j]表示i到j区间任取两个数能够异或出来的最大值,初始化dp[i, j] = a[i] ^ a[j]。
转移方程就是:\(dp_{i,j} = max(dp_{i,j}, dp_{i+1,j}, dp_{i,j-1})\)
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
int f[N][N];
int a[N];
int n, m, l, r;
int read()
{
int x = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * w;
}
int main()
{
n = read(), m = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i <= n; i++)
{
f[i][i] = a[i];
for (int j = 1; j <= n; j++)
f[i][j] = a[i] ^ a[j];
}
for (int i = n; i >= 1; i--)
for (int j = i + 1; j <= n; j++)
f[i][j] = max({f[i][j], f[i][j - 1], f[i + 1][j]});
for (int i = 1; i <= m; i++)
{
l = read(), r = read();
printf("%d\n", f[l][r]);
}
return 0;
}
Problem C
非常的Simple啊。
正解是DP和贪心。但是DP我不想不会写,于是就写个simple的贪心吧。
我们只需要考虑它是往左倒还是往右倒。而且,头和尾的两个是必砍倒得(他们肯定可以往左右中的一个方向倒)。
如果小于两棵树,那就直接输出树的棵数(不解释)。
现在就判断往左倒行不行。如果小于上一棵树的位置就不行,否则就计数器(可砍的树+1)。再判断往右倒行不行。如果行,计数器+1,并且把右面倒下的位置给占了(方便下次判断)。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int x[N], h[N];
bool vis[N];
int n, res;
int read()
{
int x = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * w;
}
int main()
{
n = read();
for (int i = 1; i <= n; i++)
x[i] = read(), h[i] = read();
if (n <= 2)
printf("%d\n", n);
else
{
res = 2;
for (int i = 2; i <= n - 1; i++)
if (x[i] - h[i] > x[i - 1])
res++;
else if (x[i] + h[i] < x[i + 1])
{
res++;
x[i] += h[i];
}
printf("%d\n", res);
}
return 0;
}
Problem D
未完待续……