1324A - Yet Another Tetris Problem(思维)
题意
- 给一个数组,每一个数组中的元素大小表示在竖直方向的方块数量,元素相邻怎竖直方向的方块也相邻,类似于俄罗斯方块当底层被堆满的时候,那么那一层可以被消去,然后我们可以在任意一个元素(数列)上 + 2 两个小方块,可以放任意多次数,问最终能不能通过这些操作能不能把所有的小方块消去。
思路
- 思路:我们可以先把底层的能消除的消除,如果消除之后 所给的数组元素中还有奇数,那么无论怎么 操作 都不能 消除完
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<map>
using namespace std;
#define ll long long
#define db double
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("A.txt","r",stdin);
int t;
cin >> t;
while(t --)
{
int n;
cin >> n;
int ar[105];
int mn = 1e9;
for(int i = 1; i <= n; i ++)
cin >> ar[i], mn = min(mn, ar[i]);
int have_odd = 0;
for(int i = 1; i <= n; i ++)
{
ar[i] -= mn;
if(ar[i] % 2 != 0)
{
have_odd = 1;
break;
}
}
if(have_odd)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
- 收获:就是一个简单的观察
1324B - Yet Another Palindrome Problem(思维)
题意
- 给一个序列,问在这个子序列中能否找到一个 回文 子串。
思路
- 这一题我们可以用 map 的特性去遍历一遍所给的数组,同在这个序列中都有哪些 数字出现过,并且记录第一次出现的位置,这样我们在从右自左遍历这个序列,我们没遍历到一个元素 我们就 用map看看是否这个 数字已经出现过了,如果没有,就去往后遍历,如果有 我们就判断两个 两个相同的数组出翔位置,的间隔差 是否大于1,如果大于,那么这两个相同的数就可以与这两个位置中的任意一个数组成一个 回文子串了;如果小于等于1 没法组成会微,继续向下遍历吧
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<map>
using namespace std;
#define ll long long
#define db double
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("A.txt","r",stdin);
int t;
cin >> t;
while(t --)
{
int n;
cin >> n;
map<int, int> mp;
int ar[50005];
for(int i = 1; i <= n; i ++)
{
cin >> ar[i];
if(! mp[ar[i]])
{
mp[ar[i]] = i;
}
}
int flag = 0;
for(int i = n; i > 1; i --)
{
if(mp[ar[i]] && i - mp[ar[i]] > 1)
{
flag = 1;
break;
}
}
if(! flag)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
- 收获:读好题,利用好map 的记录某个一个状态、某个数的位置/出现过没有,当我们把某个数带入map中之后,同过判读是否为0,就可以判读啊某个状态、位置、出现过没没有,通过一前一后呼应 来做题
1324C - Frog Jumps
题意
- 给我们一个长度为 n有 ‘L、R’ 字符组成的序列,序列下标从 1 开始,一个青wa在该序列的下标0位置,想要到下标n+1位置,开始的时候 🐸可以跳到 1~n中的任意一个表格上,之后当青蛙再次起跳时,要根据脚下的字符所代表的方向跳,并且每次 起跳的距离都要小于等于之前跳的距离(第一次跳到距离),问青蛙要想到 n+1 位置需要的最小跳距离是多少
思路(贪心)
- 分析: 这一题我们逆向到角度来看🐸跳过程,我们假设 🐸在n+1位置想要到 0位置去,如果🐸脚下的字符为 R 则想左跳,如果为L🐸向右跳,(其实就是跟正向完全相反的过程),那么这个时候到最小跳明显是在 n+1位置向左的第一次起跳且必须跳到字符为R的位置,设置个距离为 k,接下来贪心的思想去解决问题,我们假设下一次起跳 既可以跳到 ‘R’字符的位置,又可以跳动‘L’字符的位置,那么我们怎么跳呢,假如我们跳到 L字符处,那么接下来我们要向 右跳(向后跳),但是当我跳完之后,不要忘了我们最终的目的地还是 0 位置,这样之后没有必要向右(后)继续跳了,继续向右跳制只会造成接下要想在跳回左边需要更大跳跃距离(可能这个距离已经大于了k),所以这样事不划算的;那么不如我们这样想:当我们在跳完第一个跳之后这个时候的最小跳的距离为k,在以后的跳的过程中,我们一直向左跳,也就是一直跳到字符为R的 方格,如果当前的k距离可以跳到下一R字符,我们就继续跳就行了,否怎看跳到下一个 R字符到花费是多少并距离更新 k值,,,,
- 在算法开始时的时候我们可以,对所给的数组进行一些变化:1. 数组逆序过来(可略)2把逆序过的数组下标为0的位置设置为R
代码
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
#define ll long long
const int Len = 2e5 + 10;
ll ar[Len], br[Len];
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("A.txt","r",stdin);
int t;
cin >> t;
while(t --)
{
string s;
cin >> s;
char ar[s.size() + 10];
for(int i = s.size() - 1, j = 1; i >= 0; i --, j ++)
ar[j] = s[i];
ar[0] = ar[s.size()+1] = 'R';
int last = 0;
int l = 1;
int ans = 0;
while(l <= s.size())
{
for(int i = last + 1; i <= s.size() + 1; i ++)
{
if(ar[i] == 'R')
{
l = i;
break;
}
}
ans = max(ans, l - last);
last = l;
}
cout << ans << endl;
}
return 0;
}
- 收获:仔细分析🐸跳跃的过程,好好的利用贪心的思路,看看每一跳应该往哪跳,每一跳的关系
1324D - Pair of Topics
题意
给我们两个 长度为n 的序列 a 1 a 2 a 3 . . . a n a_{1} a_{2} a_{3} ... a_{n} a1a2a3...an b 1 b 2 b 3 . . . b n b_{1} b_{2} b_{3} ... b_{n} b1b2b3...bn 问 在 i < j 的 情 况 下 , a i + a j > a i + a j 的 组 合 有 多 少 对 i 、 j 满 足 前 面 这 个 不 等 式 问在 i < j的情况下,a_{i} + a_{j} > a_{i} + a_{j}的组合有多少对i、j满足前面这个不等式 问在i<j的情况下,ai+aj>ai+aj的组合有多少对i、j满足前面这个不等式 思 路 : 我 们 可 以 对 上 面 的 不 等 式 进 行 变 换 为 : a i − b i + a j − b j > 0 , 那 么 我 们 假 设 c i = a i − a j , 那 么 我 们 就 让 原 来 的 两 个 数 组 变 成 了 一 个 数 组 的 关 系 : c i − c j > 0 , 变 成 一 个 数 组 就 好 处 理 多 了 , 剩 下 的 就 看 代 码 吧 。 。 。 思路:我们可以对上面的不等式进行变换为:a_{i} - b_{i} + a_{j} - b_{j} > 0, 那么我们假设 c_{i} = a_{i} - a{j}, 那么我们就让原来的两个数组 变成了 一个数组的关系: c_{i} - c_{j} > 0 ,变成一个数组就好处理多了,剩下的就看代码吧。。。 思路:我们可以对上面的不等式进行变换为:ai−bi+aj−bj>0,那么我们假设ci=ai−aj,那么我们就让原来的两个数组变成了一个数组的关系:ci−cj>0,变成一个数组就好处理多了,剩下的就看代码吧。。。
代码
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int Len = 2e5 + 10;
ll ar[Len], br[Len];
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("A.txt","r",stdin);
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> ar[i];
for(int i = 1; i <= n; i ++)
cin >> br[i], ar[i] -= br[i];
sort(ar + 1, ar + 1 + n);
ll l = 1, r = n;
ll ans = 0;
while(l < r)
{
if(ar[l] + ar[r] > 0)
ans += r - l, r --;
else
l ++;
}
cout << ans << endl;
return 0;
}
- 收获
1324E - Sleeping Schedule (动态规划 + 细节)
题意
一个人一天睡 n 次觉,每一天有h小时,在 l~r的时间段内 为最好时间段,在刚开始睡觉开始的时间为0时, 在 第 i 次 的 时 候 可 以 选 择 在 a i 小 时 后 入 睡 , 也 可 以 在 a i − 1 小 时 后 入 睡 , 问 在 n 次 睡 觉 中 最 多 有 几 次 在 l ~ r 区 间 内 入 睡 的 在第i次的时候可以选择在 a_{i}小时后入睡,也可以在 a_{i}-1 小时后入睡,问在n次睡觉中 最多有几次在l~r区间内入睡的 在第i次的时候可以选择在ai小时后入睡,也可以在ai−1小时后入睡,问在n次睡觉中最多有几次在l~r区间内入睡的
思路
- 很明显这是一道类似于背包问题的dp问题,在第 i 次进入睡眠的时候,我们是从i-1次进入睡眠的的基础上推倒过来的,那么我们可以推导出状态转移方程:
dp[i][j] = max(dp[i][j], max(dp[i - 1][ (j - ar[i] + h) %h + dp[i - 1][ (j - ar[i] + 1 + h) %h ] ) ) + check()
其中: j 是指 第j时,
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int mxn = 2e3 + 10;
int ar[mxn];
int dp[mxn][mxn];
int main()
{
//freopen("A.txt","r",stdin);
int n, h, l, r;
scanf("%d %d %d %d", &n, &h, &l, &r);
for(int i = 1; i <= n; i ++)
scanf("%d", &ar[i]);
//一开始初始化为-1不要忘了,因为不是所有的点都可以转到其实状态上来
memset(dp, -1, sizeof(dp));
int c1,c2;
c1 = ar[1];
c2 = ar[1] - 1;
//这里一开始,要么方案数是0,要么位于最优睡觉区间上是1
dp[1][c1] = (c1 >= l && c1 <= r) ? 1 : 0;
dp[1][c2] = (c2 >= l && c2 <= r) ? 1 : 0;
int ans = max(dp[1][c1], dp[1][c2]);
for(int i = 2; i <= n; i ++)
for(int j = 0; j <= h; j ++)
{
c1 = (j - ar[i] + h) % h;
c2 = (j - ar[i] + 1 + h) % h;
if(dp[i - 1][c1] < 0 && dp[i - 1][c2] < 0) continue;
dp[i][j] = max(dp[i][j], max(dp[i - 1][c1], dp[i - 1][c2])) + (j >= l && j <= r ? 1 : 0);
}
//这里的for循环是用来判断,数据是否只有一组,如果不是找到最优方案数
for(int i = 0; i < h; i ++)
ans = max(ans, dp[n][i]);
printf("%d\n", ans);
return 0;
}
- 收获:多做一点dp题,做得时候思路少的可怜。。。。。。。。。