100307. 候诊室中的最少椅子数
原题链接
100307. 候诊室中的最少椅子数
思路分析
直接模拟
时间复杂度:O(n)
AC代码
class Solution:def minimumChairs(self, s: str) -> int:cur = res = 0for x in s:if x == 'E':cur += 1else:cur -= 1res = max(res, cur)return res
100311. 无需开会的工作日
原题链接
100311. 无需开会的工作日
思路分析
区间合并类问题,区间合并后得到若干不相交的区间,数轴上没有被区间覆盖的长度和就是答案
结尾空隙别忘记加
时间复杂度O(nlogn)
AC代码
class Solution:def countDays(self, days: int, meetings: List[List[int]]) -> int:meetings.sort(key=lambda x: x[0])ed = res = 0for l, r in meetings:if l > ed:res += min(l, days) - ed - 1ed = relse:ed = max(ed, r)res += max(0, days - ed)return res
100322. 删除星号以后字典序最小的字符串
原题链接
100322. 删除星号以后字典序最小的字符串
思路分析
直接顺序遍历,维护每个小写字母的出现下标集合
遇到星号就把当前出现的字典序最小的字母的最右左边打标记
最终返回原字符串中除去打标记和'*'的部分
时间复杂度:O(nU)
AC代码
class Solution:def clearStars(self, s: str) -> str:n = len(s)vis = [False] * nst = [[] for _ in range(26)]for i, x in enumerate(s):if x == '*':for j in range(26):if st[j]:vis[st[j][-1]] = Truest[j].pop()breakvis[i] = Trueelse:st[ord(x) - ord('a')].append(i)return ''.join([s[i] for i in range(n) if not vis[i]])
100315. 找到按位与最接近 K 的子数组
原题链接
100315. 找到按位与最接近 K 的子数组
思路分析
没想到好方法,用的线段树+二分
因为固定左端点的前缀与越靠右越小
我们枚举左端点,二分出第一个大于等于 k 的右端点,然后下一个下标就是第一个小于k的右端点,二者贡献出的两个绝对差来对答案进行维护
时间复杂度O(n log^2 n)
应该有更好的方法,比如按位拆分?赛后看下题解区吧
2024.06.02 12:43 吃完饭回来,看评论区说是原题,而且那原题我还做过……去年做的忘了都
F2 ST表+二分
比线段树少个log,跑了300ms
F3 倒序遍历+原地去重
因为所有位置任意长度后缀按位与的值的数目为log级别的,所以我们倒序遍历维护后缀按位与的集合即可,且因为按位与单调递减,我们可以原地去重来维护
这个方法最快,是150ms
AC代码
#define lc p << 1
#define rc p << 1 | 1
constexpr int N = 1e5 + 10;
int tr[N * 4];
// 向上更新
void pushup(int p)
{tr[p] = tr[lc] & tr[rc];
}void build(int p, int l, int r, vector<int>& a)
{tr[p] = a[l];if (l == r)return;int mid = (l + r) >> 1;build(lc, l, mid, a);build(rc, mid + 1, r, a);pushup(p);
}int query(int p, int l, int r, int L, int R)
{if (L <= l && r <= R)return tr[p];int mid = l + r >> 1, res = (1 << 30) - 1;if (L <= mid)res &= query(lc, l, mid, L, R);if (R > mid)res &= query(rc, mid + 1, r, L, R);return res;
}
#undef lc
#undef rc
class Solution {
public:int minimumDifference(vector<int>& a, int k) {int n = a.size();build(1, 0, n - 1, a);int res = abs(tr[1] - k);for (int i = 0; i < n; i ++ ) {int l = i, r = n - 1, ans = -1;while (l <= r) {int mid = l + r >> 1;if (query(1, 0, n - 1, i, mid) >= k)ans = mid, l = mid + 1;else r = mid - 1;} if (ans == -1) {l = r = i;// cout << a[i] << '\n';res = min(res, abs(a[i] - k));continue;}l = ans, r = min(n - 1, ans + 1);// cout << query(1, 0, n - 1, i, r) << " " << query(1, 0, n - 1, i, l) << '\n';res = min(res, min(abs(query(1, 0, n - 1, i, r) - k), abs(query(1, 0, n - 1, i, l) - k)));}return res;}
};