飞机直达
A
题意思路略
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[4];
signed main()
{
int t;
cin >> t;
while(t --){
for(int i = 0 ; i < 3; i ++){
cin >> a[i];
}
sort( a, a + 3);
int ans = 0;
if(a[0] == a[1] && a[1]== a[2]){
cout << 0 << endl;
continue;
}
if(a[0] == a[1] || a[1] == a[2]){
if(a[0] == a[1]){
if(a[2] - a[1] <= 1){
cout << 0 << endl;
continue;
}
else {
a[0] ++;
a[2] --;
ans = (a[2] - a[0])*2;
}
}
else {
if(a[1] - a[0] <= 1){
cout << 0 << endl;
continue;
}
else {
a[0] ++;
a[2] --;
ans = (a[2] - a[0])*2;
}
}
}
else{
a[0] ++;
a[2] --;
ans += a[1] - a[0];
ans += a[2] - a[1];
ans += a[2] - a[0];
}
cout << ans<< endl;
}
}
B
题意思路略
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[4];
signed main()
{
int t;
cin >> t;
while(t --){
string s;
cin >> s;
int a = 0, b= 0,c = 0, d = 0;
for(int i = 0 ; i < s.size();i ++){
if(s[i] == 'U') a++;
else if(s[i] == 'D') b++;
else if(s[i] == 'R') c++;
else if(s[i] == 'L') d++;
}
int ans = 0;
if(a && b && c && d){
ans = min(a,b)*2 + min(c,d) * 2;
cout << ans << endl;
for(int i = 0 ; i < min(a,b); i ++){
cout <<"U";
}
for(int i = 0 ; i < min(c,d); i ++){
cout << "R";
}
for(int i = 0 ; i < min(a, b); i ++){
cout <<"D";
}
for(int i = 0; i < min(c,d); i ++){
cout <<"L";
}
}
else {
if(a&&b){
cout << 2 << endl;
cout << "UD";
}
else if(c&&d){
cout << 2 << endl;
cout <<"LR";
}
else{
cout << 0 << endl;
}
}
cout << endl;
}
}
C
题意思路略
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[4];
int vis[26];
signed main()
{
int n,k;
cin >> n >> k;
string s;
cin >> s;
for(int i = 0 ; i< k; i ++){
char c;
cin >> c;
vis[c - 'a'] ++;
}
std::vector<int> v;
int len = 0 ;
for(int i = 0 ;i < s.size(); i ++){
if(vis[s[i] - 'a']){
len ++;
}
else{
v.push_back(len);
len = 0;
}
}
v.push_back(len);
int ans = 0;
for(int i = 0 ;i < v.size() ; i ++){
ans += v[i]*(v[i] + 1)/2;
}
cout << ans << endl;
}
D
维护i的左右长度,每个数都删除一次然后去最长
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[200005];
int l[200005];
int r[200004];
signed main()
{
int n;
cin >> n;
for(int i = 0 ; i< n; i ++){
cin >> a[i];
}
std::vector<int> v;
int len = 1;
r[n - 1] = len;
for(int i = n - 2; i >= 0; i --){
if(a[i + 1] - a[i] > 0){
len ++;
r[i] = len;
}
else{
len = 1;
r[i] = len;
}
}
l[0] = 1;
len = 1;
for(int i = 1; i <= n - 1; i ++){
if(a[i] - a[i - 1] > 0){
len ++;
l[i] = len;
}
else{
len = 1;
l[i] = len;
}
}
int ans = 0;
for(int i = 0; i < n - 2;i ++){
ans = max(ans, l[i]);
if(a[i + 2] - a[i] > 0){
ans = max(ans, l[i] + r[i + 2]);
//cout << i <<" " << l[i] <<" " << r[i] << endl;
}
}
ans = max(ans, max(l[n - 2],l[n - 1]));
cout << ans << endl;
}
E
题意就是让你从每个位置开始每次可以跳到
i
+
a
[
i
]
i + a[i]
i+a[i] 或者
i
−
a
[
i
]
i - a[i]
i−a[i]问你对于每个位置来说,跳到与该位置奇偶性不同的位置的最小步数。
思路:
我们应该先搞清楚,从当前位置开始跳的话 应该是从1开始增加一直到与它奇偶性不同的位置一直增加到n(假设n步可达),那么我们怎么记录这个增加的过程呢,只需要反向建边,那么我们从第n到的点开始搜,因为前n - 1步到的点一定是与第一步的点的奇偶性是相同的,所以从n开始往前bfs 每次增加一就行
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 200005;
std::vector<int> v[maxn];
int a[maxn];
int ans[maxn];
signed main()
{
int n;
cin >> n;
for(int i = 0; i <= n; i ++){
ans[i] = -1;
}
for(int i = 1; i <= n;i ++){
cin >> a[i];
}
queue<int> q;
for(int i = 1; i <= n; i ++){
if(i + a[i] <= n){
v[i + a[i]].push_back(i);
if(a[i] % 2 != a[i + a[i]] % 2){
q.push(i);
ans[i] = 1;
}
}
if(i - a[i] >= 1){
v[i - a[i]].push_back(i);
if(a[i] % 2 != a[i - a[i]] % 2){
q.push(i);
ans[i] = 1;
}
}
}
while(!q.empty()){
int u = q.front();
q.pop();
//cout << u << endl;
for(int i = 0; i < v[u].size() ; i ++){
int x = v[u][i];
if(ans[x] == -1){
ans[x] = ans[u] + 1;
q.push(x);
}
}
}
for(int i = 1; i <= n; i ++){
cout << ans[i] <<" ";
}
cout << endl;
}
F
题意
给你两个括号序列,让你输出最短的完备括号序列,要求给你的两个括号序列是这个的子序列。
思路
记忆化搜索 或 dp
这个题可参考网上的思路。
三维 i, j ,k 表示第一个字符串到i, 第二个字符串到j, 当前前缀和为k(这个前缀和代表左括号为1,右括号为-1)
记录位置,递归输出
#include <bits/stdc++.h>
using namespace std;
int dp[205][205][405];
string s,s1;
pair<int , pair<int, int>> nx[205][205][405];
int vis[205][205][405];
int dfs(int i, int j, int len){
if(len < 0 || len >= s.size() + s1.size()) return 100000000;
if(i == s.size() &&j == s1.size() ) return len;
if(dp[i][j][len] != -1) return dp[i][j][len];
dp[i][j][len] = 100000000;
int dp1 = dfs(
((i < s.size()&&s[i] == '(')?i + 1:i),
((j < s1.size()&&s1[j] == '(')?j + 1:j),
len + 1) + 1;//len + 1是当前答案的前缀和 + 1,最后+1是答案的长度+1
int dp2 = dfs(
((i < s.size()&&s[i] == ')')?i+ 1:i),
((j < s1.size()&&s1[j] == ')')?j + 1:j),
len - 1) + 1;
if(dp1 < dp2){//找到当前位置是放左括号最优还是右括号记录位置
vis[i][j][len] = 1;
nx[i][j][len] = make_pair((i < s.size()&&s[i] == '(')?i+ 1:i,make_pair((j < s1.size()&&s1[j] == '(')?j + 1:j,len + 1));
}
else {
vis[i][j][len] = 2;
nx[i][j][len] = make_pair((i < s.size()&&s[i] == ')')?i+ 1:i,make_pair((j < s1.size()&&s1[j] == ')')?j + 1:j,len - 1));
}
dp[i][j][len] = min(dp1, dp2);
return dp[i][j][len];
}
void print(int i, int j, int len){
//cout<<i<<" "<<j<<" "<<len<<" "<<nx[i][j][len].first<<" "<<nx[i][j][len].second.first<<" "<<nx[i][j][len].second.second<<" "<<dp[i][j][len]<<" "<<vis[i][j][len]<<endl;
if(vis[i][j][len] == 1){
cout << '(';
print(nx[i][j][len].first, nx[i][j][len].second.first, nx[i][j][len].second.second);
}
else if(vis[i][j][len] == 2){
cout << ')';
print(nx[i][j][len].first, nx[i][j][len].second.first, nx[i][j][len].second.second);
}
else {
if(len > 0){
for(int i = 0; i < len; i ++){
cout << ")";
}
}
return ;
}
}
int main()
{
cin >> s >> s1;
memset(dp, -1, sizeof dp);
dfs(0,0,0);
print(0,0,0);
}