100307. 候诊室中的最少椅子数
原题链接
思路分析
直接模拟
时间复杂度:O(n)
AC代码
class Solution:
def minimumChairs(self, s: str) -> int:
cur = res = 0
for x in s:
if x == 'E':
cur += 1
else:
cur -= 1
res = max(res, cur)
return res
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 = 0
for l, r in meetings:
if l > ed:
res += min(l, days) - ed - 1
ed = r
else:
ed = max(ed, r)
res += max(0, days - ed)
return res
100322. 删除星号以后字典序最小的字符串
原题链接
思路分析
直接顺序遍历,维护每个小写字母的出现下标集合
遇到星号就把当前出现的字典序最小的字母的最右左边打标记
最终返回原字符串中除去打标记和'*'的部分
时间复杂度:O(nU)
AC代码
class Solution:
def clearStars(self, s: str) -> str:
n = len(s)
vis = [False] * n
st = [[] for _ in range(26)]
for i, x in enumerate(s):
if x == '*':
for j in range(26):
if st[j]:
vis[st[j][-1]] = True
st[j].pop()
break
vis[i] = True
else:
st[ord(x) - ord('a')].append(i)
return ''.join([s[i] for i in range(n) if not vis[i]])
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;
}
};