AcWing第65场周赛
思路:我是真的傻,看错题目了两次(第一次看成前缀和,第二次看成求和,后来发现是最大值)。双指针求最大值。
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int t; cin >> t;
while(t --)
{
int n;
string s;
cin >> n >> s;
int ans = 0;
for(int i = 0; i < n; i ++)
{
if(s[i] == 'A')
{
int j = i + 1;
while(j < n && s[j] == 'P') j ++;
ans = max(ans, j - i - 1);
}
}
cout << ans << endl;
}
return 0;
}
思路:第一次是向用哈希表来存储每个数和这个数的次数,然后来枚举,后来超时了。因为字符串的最大值为18,所以每次将字符串长度扩展为18(长度不足18的补上前导0),用哈希表来存储这些字符串,所以每次插入、删除、询问的时间复杂度都是18,所以总时间复杂度最大为18*100000是可以过的。
代码
#include <bits/stdc++.h>
using namespace std;
unordered_map<string, int> mp;
string get(string s)
{
string res;
for(int i = 0; i < s.size(); i ++)
if((s[i] - '0') & 1) res.push_back('1');
else res.push_back('0');
while(res.size() < 18) res = "0" + res;
// cout << res << endl;
return res;
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int t; cin >> t;
while(t --)
{
char op;
string a;
cin >> op >> a;
if(op == '+')
mp[get(a)] ++;
else if(op == '-')
mp[get(a)] --;
else
cout << mp[get(a)] << endl;
}
return 0;
}
力扣第85场双周赛
第一题:2379. 得到 K 个黑块的最少涂色次数 - 力扣(LeetCode)
思路:定长滑动窗口求最小值。直接两层循环(一层枚举起点,另一层枚举终点(长度不能大于窗口的长度)),找出白色个数的最小值。
代码
class Solution {
public:
int minimumRecolors(string b, int k) {
int ans = k;
int n = b.size();
for(int i = 0; i <= n - k; i ++)
{
int cnt = 0;
for(int j = 0; j < k; j ++)
{
if(b[i + j] == 'W')
cnt ++;
}
ans = min(ans, cnt);
}
return ans;
}
};
第二题:2380. 二进制字符串重新安排顺序需要的时间 - 力扣(LeetCode)
思路:我原本还以为是找规律,找了半天(wa了两次,还是没有过),后来看了一下通过人数觉得可能是模拟,用模拟写了一下过了,我是**。将01变为10,在这其中1和0的个数都没有发生改变,并且最后会变成111...10....0这样的形式(因为最后不能存在01),每次对字符串进行变形(将01变为10),直到最后是111..10...0的形式。
代码
class Solution {
public:
int secondsToRemoveOccurrences(string s) {
int cnt = 0, n = s.size();
for(auto i : s) if(i == '1') cnt ++;
string t;
for(int i = 0; i < n; i ++)
{
if(i + 1 <= cnt) t += "1";
else t += "0";
}
int ans = 0;
while(1)
{
if(s == t) break;
for(int i = 0; i < n; i ++)
{
if(s[i] == '0' && i + 1 < n && s[i + 1] == '1')
{
swap(s[i], s[i + 1]);
i ++;
}
}
ans ++;
}
return ans;
}
};
第三题:2381. 字母移位 II - 力扣(LeetCode)
思路:差分。连续的区间并且想前变化和想后变化所以就想到了差分。向后移+1,向前移-1,最后用前缀和求出每个位置需要向一个方向(整数向后移动,负数向前移动)移动多少位(注意这个要对26取模,因为是a-z循环)。
代码
class Solution {
public:
string shiftingLetters(string s, vector<vector<int>>& shifts) {
int n = s.size();
vector<int> res(n + 1, 0);
for(auto i : shifts)
{
int l = i[0], r = i[1], c = i[2];
if(c == 0) c = -1;
res[l] += c, res[r + 1] -= c;
}
for(int i = 1; i < n; i ++) res[i] += res[i - 1];
for(int i = 0; i < n; i ++)
{
int t = ((s[i] - 'a' + res[i]) % 26 + 26) % 26; //这里要先对26取模,因为负数的余数也是负数
s[i] = t + 'a';
}
return s;
}
};
力扣第 307场周赛
OS:这次的周赛前两题是我做过的最难的前两题。
第一题:2383. 赢得比赛需要的最少训练时长 - 力扣(LeetCode)
思路:因为精力每次都会减少,所以初始精力要大于所消耗的精力之和。而经验是每次相比进行比较,少了就加上少的加1,注意每次都加上经验。
代码
class Solution {
public:
int minNumberOfHours(int t, int e, vector<int>& energy, vector<int>& x) {
int ans = 0, sum = 0;
int n = x.size();
for(int i = 0; i < n; i ++)
{
int a = energy[i], b = x[i];
sum += a;
if(e <= b) ans += b + 1 - e, e += b + 1 - e;
e += b;
}
if(t <= sum) ans += sum + 1 - t;
return ans;
}
};
第二题:2384. 最大回文数字 - 力扣(LeetCode)
思路:统计每个数字出现的次数。将每个数组从大到小进行遍历。先存储回文字符串的前一半,最后将存储的字符串翻转在加到存储的字符串的后面就是回文串了。
对于每个数字出现的次数x进存储(该数字存储x/2次),注意存储一个最大的数字的奇数次的数字op,因为是从大到小枚举的,如果存在奇数次就将一个字符变成该数字。
最后回文串为x(去掉前导0)+op(如果存在)+x'(将x翻转)。
代码
class Solution {
public:
string largestPalindromic(string num) {
map<int, int> mp;
for(auto i : num) mp[i - '0'] ++;
vector<pair<int, int>> ans;
for(auto [x, y] : mp)
ans.push_back({x, y});
sort(ans.begin(), ans.end(), greater());
string s;
bool st = 0;
char op;
for(auto i : ans)
{
int a = i.first, b = i.second;
if(!st && b & 1)
{
op = a + '0';
st = 1;
b --;
}
for(int i = 0; i < b / 2; i ++) s += to_string(a);
}
int i = 0;
while(i < s.size() && s[i] == '0') i ++;
s = s.substr(i);
string t = s;
reverse(t.begin(), t.end());
if(st) s.push_back(op);
s += t;
if(!st && !s.size()) s = "0"; //可以num是偶数个0
return s;
}
};
第三题:2385. 感染二叉树需要的总时间 - 力扣(LeetCode)
思路:数的存储+bfs遍历。将该数以邻接表存储用bfs求到最远叶子节点的层数。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
const int N = 100010, M = N * 2;
class Solution {
public:
int h[N], e[M], ne[M], idx;
bool st[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void build(TreeNode* root)
{
if(root->left != NULL)
{
add(root->val, root->left->val);
add(root->left->val, root->val);
build(root->left);
}
if(root->right != NULL)
{
add(root->val, root->right->val);
add(root->right->val, root->val);
build(root->right);
}
}
int amountOfTime(TreeNode* root, int start) {
memset(h, -1, sizeof h);
build(root);
queue<int> q;
int ans = 0;
q.push(start);
st[start] = 1;
while(q.size())
{
int n = q.size();
while(n --)
{
auto p = q.front(); q.pop();
for(int i = h[p]; i != -1; i = ne[i])
{
int j = e[i];
if(!st[j])
{
q.push(j);
st[j] = 1;
}
}
}
ans ++;
}
ans --;
return ans;
}
};