题目链接
#include
#include
#include
using namespace std;
int main()
{
int n;
string s;
cin >> n >> s;
unordered_set<char> S;
for (auto c : s)
S.insert(tolower(c));
if (S.size() == 26) puts("YES");
else puts("NO");
return 0;
}
题目链接
选择其中一个基站,每次从大到小枚举该基站的半径,每一次抛出去一个点,用于更新另一个基站的半径。当一个基站的半径固定的时候,另外一个基站的半径也一定是固定的。
并且可以知道,最后的结果一定是一个整数,题目中给出"答案四舍五入到个位"是无用的。因为最终圆的边一定在某一个点上,这个点到圆心的半径一定是一个整数。如果半径大于这个点到圆心的距离,那么这个圆是可以缩小的。
排序 O ( l o g n ) O(logn) O(logn),枚举一个圆的半径 O ( n ) O(n) O(n),求另一个圆的半径 O ( 1 ) O(1) O(1),总的时间复杂度 O ( l o g n ) O(logn) O(logn)。
#include
#include
#include
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 2010;
int n;
PII s1, s2;
PII q[N];
LL dist(PII a, PII b) {
LL dx = a.x - b.x, dy = a.y - b.y;
return dx * dx + dy * dy;
}
bool cmp(PII a, PII b) {
return dist(s1, a) < dist(s1, b);
}
int main() {
cin >> n >> s1.x >> s1.y >> s2.x >> s2.y;
for (int i = 0; i < n; i++) cin >> q[i].x >> q[i].y;
sort(q, q + n, cmp);
LL res = 1e18, r = 0;
for (int i = n - 1; i >= 0; i--) {
res = min(res, dist(q[i], s1) + r);
r = max(r, dist(q[i], s2));
}
res = min(res, r);
printf("%lld\n", res);
return 0;
}
题目链接
题目给出,只有两种变换方法,要么左括号变成右括号,要么右括号变成左括号,变换之后左右括号数量相同。
首先字符串长度必须为偶数,否则返回0;
然后统计字符串中所有左括号和右括号的数量,分别记为 l 、 r l、r l、r。如果它们差的绝对值不为2
,则一定没有合法方案,输出0
。即它们应该满足
当左括号的数量多于右括号的时候,令左括号的值为1
,右括号的值为-1
,为了满足题目条件对于 s 的任意前缀字符串,其中包含的 ( 的数量均不少于 ) 的数量
,可以得出任意前缀字符串的前缀和不能<= 0
。从左往右扫描,扫描到第一次出现前缀和< 0
,即左括号的数量小于右括号数量少的时候,就需要要修改一个右括号为左括号,这时候可以修改的方案数为前面右括号的数量。对于每一种方案,修改完之后还需要观察后面所有的前缀和是否满足,如果满足,即为答案。
当右括号的数量多于左括号的时候,先将其镜像,然后左右括号互换,将此问题转换为为当左括号的数量多于右括号的情况,用上面的方法求解。
#include
#include
#include
using namespace std;
const int N = 1e6 + 10;
int n;
char s[N];
int work() {
int cnt = 0, r = 0; // 前缀和cnt,右括号数量r
for (int i = 0; i < n; i++)
if (s[i] == '(') cnt++;
else {
cnt--; r++;
if (cnt < 0) {
cnt += 2;
for (int j = i + 1; j < n; j++)
if (s[j] == '(') cnt++;
else {
cnt--;
if (cnt < 0) return 0;
}
return r; // 前面右括号的数量即为方案数
}
}
return 0;
}
int main() {
scanf("%d%s", &n, s);
int l = 0, r = 0;
for (int i = 0; i < n; i++)
if (s[i] == '(') l++;
else r++;
if (r == l + 2) printf("%d\n", work());
else if (l == r + 2) {
reverse(s, s + n);
for (int i = 0; i < n; i++)
if (s[i] == '(') s[i] = ')';
else s[i] = '(';
printf("%d\n", work());
} else puts("0");
return 0;
}
题目链接
class Solution {
public:
vector<int> add(vector<int> q) {
vector<int> res(q.size() / 2);
for (int i = 0; i < q.size() / 2; i++) {
if (i % 2)
res[i] = max(q[i * 2 + 1], q[2 * i]);
else res[i] = min(q[i * 2 + 1], q[2 * i]);
}
return res;
}
int minMaxGame(vector<int> &nums) {
if (nums.size() == 1) return nums[0];
vector<int> ans = add(nums);
while (ans.size() != 1)
ans = add(ans);
return ans[0];
}
};
题目链接
class Solution {
public:
int partitionArray(vector<int> &nums, int k) {
sort(nums.begin(), nums.end());
int n = nums.size(), i, j, ans = 0;
for (i = 0; i < n; i = j) {
for (j = i + 1; j < n && nums[j] - nums[i] <= k; j++);
ans++;
}
return ans;
}
};
题目链接
class Solution {
public:
vector<int> arrayChange(vector<int> &nums, vector <vector<int>> &operations) {
unordered_map<int, int> mp;
for (int i = 0; i < nums.size(); i++)
mp[nums[i]] = i;
for (auto c: operations) {
int index = mp[c[0]];
mp.erase(c[0]);
mp[c[1]] = index;
nums[index] = c[1];
}
return nums;
}
};
题目链接
class TextEditor {
public:
stack<char> a, b;
TextEditor() {
a = stack<char>();
b = stack<char>();
}
void addText(string text) {
for (auto c: text)
a.push(c);
}
int deleteText(int k) {
int target = k;
while (k > 0 && !a.empty())
a.pop(), k--;
return target - k;
}
string cursorLeft(int k) {
while (!a.empty() && k > 0) {
b.push(a.top());
a.pop();
k--;
}
return readLeftChar();
}
string cursorRight(int k) {
while (!b.empty() && k > 0) {
a.push(b.top());
b.pop();
k--;
}
return readLeftChar();
}
string readLeftChar() {
if (a.empty()) return "";
string res = "";
while (res.size() < 10 && !a.empty()) {
res += a.top();
a.pop();
}
reverse(res.begin(), res.end());
// 恢复栈
for (auto c: res)
a.push(c);
return res;
}
};
题目链接
class Solution {
public:
bool strongPasswordCheckerII(string a) {
if (a.size() < 8) return false;
set<char> st = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+'};
bool is_l = false, is_u = false, is_d = false, is_c = false, is_s = false;
for (auto c: a) {
if (c >= 'a' && c <= 'z') is_l = true;
if (c >= 'A' && c <= 'Z') is_u = true;
if (c >= '0' && c <= '9') is_d = true;
if (st.count(c)) is_c = true;
}
for (int i = 1; i < a.size(); i++)
if (a[i] == a[i - 1])
is_s = true;
if (is_l && is_u && is_d && is_c && !is_s) return true;
return false;
}
};
题目链接
⌈ a b ⌉ = ⌊ a + b − 1 b ⌋ ( a > 0 , b > 0 ) \left \lceil \frac{a}{b} \right \rceil = \left \lfloor \frac{a + b - 1}{b} \right \rfloor(a >0, b > 0) ⌈ba⌉=⌊ba+b−1⌋(a>0,b>0)
class Solution {
public:
vector<int> successfulPairs(vector<int>& a, vector<int>& b, long long c) {
int n = a.size();
sort(b.begin(), b.end());
vector<int> res;
for (int i = 0; i < n; i ++ )
{
int k = lower_bound(b.begin(), b.end(), (c + a[i] - 1) / a[i]) - b.begin();
res.push_back(b.size() - k);
}
return res;
}
};
题目链接
class Solution {
public:
bool matchReplacement(string a, string b, vector <vector<char>> &mappings) {
unordered_set<int> hash;
for (auto &p: mappings) hash.insert(p[0] * 256 + p[1]);
int n = a.size(), m = b.size();
for (int i = 0; i + m - 1 < n; i++) {
bool flag = true;
for (int j = 0; j < m; j++) {
if (a[i + j] != b[j] && !hash.count(b[j] * 256 + a[i + j])) {
flag = false;
break;
}
}
if (flag) return true;
}
return false;
}
};
题目链接
class Solution {
public:
long long countSubarrays(vector<int>& nums, long long k) {
int n = nums.size();
vector<long long> s(n + 1);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + nums[i - 1];
long long res = 0;
for (int i = 1, j = 0; i <= n; i ++ ) {
while ((s[i] - s[j]) * (i - j) >= k) j ++ ;
res += i - j;
}
return res;
}
};
题目链接
#include
#include
using namespace std;
const int N = 15;
int n, m;
int a[N], b[N];
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < m; i++) cin >> b[i];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
if (a[i] == b[j]) {
cout << a[i];
if (i < n - 1) cout << " ";
break;
}
}
cout << endl;
return 0;
}
题目链接
二分:手写二分 O ( n l o g n ) O(nlogn) O(nlogn)
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 200010, INF = 2e9;
int n, m;
int c[N], a[N], b[N];
int ans[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n + m; i++) scanf("%d", &c[i]);
for (int i = 0, j = 0, k = 0; i < n + m; i++) {
int t; scanf("%d", &t);
if (t) b[++j] = c[i];
else a[++k] = c[i];
}
b[0] = -INF, b[m + 1] = INF;
for (int i = 1; i <= n; i++) {
int l = 0, r = m + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (b[mid] >= a[i]) r = mid;
else l = mid + 1;
}
if ((LL) a[i] - b[r - 1] <= (LL) b[r] - a[i]) ans[r - 1]++;
else ans[r]++;
}
for (int i = 1; i <= m; i++) printf("%d ", ans[i]);
return 0;
}
二分:库函数二分 O ( n l o g n ) O(nlogn) O(nlogn)
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 10, INF = 2e9;
int n, m;
int c[N], a[N], b[N];
int ans[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n + m; i++) scanf("%d", &c[i]);
for (int i = 0, j = 0, k = 0; i < n + m; i++) {
int t; scanf("%d", &t);
if (t) b[++j] = c[i];
else a[++k] = c[i];
}
b[0] = -INF, b[m + 1] = INF;
for (int i = 1; i <= n; i++) {
int r = lower_bound(b, b + m + 2, a[i]) - b;
if ((LL) a[i] - b[r - 1] <= (LL) b[r] - a[i]) ans[r - 1]++;
else ans[r]++;
}
for (int i = 1; i <= m; i++) printf("%d ", ans[i]);
return 0;
}
双指针 O ( n ) O(n) O(n)
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 200010, INF = 2e9;
int n, m;
int c[N], a[N], b[N];
int ans[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n + m; i++) scanf("%d", &c[i]);
for (int i = 0, j = 0, k = 0; i < n + m; i++) {
int t; scanf("%d", &t);
if (t) b[++j] = c[i];
else a[++k] = c[i];
}
b[0] = -INF, b[m + 1] = INF;
for (int i = 1, j = 0; i <= n; i++) {
while (b[j] < a[i]) j++; // 找到第一个比a[i]大的坐标
int r = j;
if ((LL) a[i] - b[r - 1] <= (LL) b[r] - a[i]) ans[r - 1]++;
else ans[r]++;
}
for (int i = 1; i <= m; i++) printf("%d ", ans[i]);
return 0;
}
题目链接
首先考虑暴力做法。设状态数组 b o o l f ( i , j , a , b ) bool \space f(i,j,a,b) bool f(i,j,a,b) 表示当前向左走 a a a次,向右走了 b b b次能否到达 ( i , j ) (i,j) (i,j)这个格子,则有状态转移表示
对于每一个状态,看是否满足 a ≥ x , b ≥ y a \ge x, b \ge y a≥x,b≥y即可,时间复杂度为 O ( n 4 ) O(n^4) O(n4)。
优化:将状态表示中的某一维放入值里面,即 f ( i , j , a ) f(i,j,a) f(i,j,a)表示当前往左走 a a a次,往右最少走几次能够到达 ( i , j ) (i,j) (i,j),且状态应该满足 f ( i , j , a ) ≤ y f(i,j,a) \le y f(i,j,a)≤y,这个时候时间复杂度为 O ( n 3 ) O(n^3) O(n3)。
进一步优化:不妨设图中存在两个点 ( r , c ) 、 ( i , j ) (r, c)、(i, j) (r,c)、(i,j),且 c < j c < j c<j。现在要从 ( r , c ) (r,c) (r,c),往左走 a a a步,往右走 b b b,最终走到 ( i , j ) (i, j) (i,j),则存在如下关系 j − c = b − a ⇒ a = b − ( j − c ) \begin{aligned} &j - c = b - a \\ \Rightarrow &a= b - (j - c)\\ \end{aligned} ⇒j−c=b−aa=b−(j−c)可见 a 、 b a、b a、b之间是正相关的,二者知道其中一个最小值就可以求出另外一个最小值,所以状态表示可以再减少一维,即 f ( i , j ) f(i,j) f(i,j)表示走到 ( i , j ) (i,j) (i,j)这个格子,往右最少走几步。
因为状态之间存在依赖关系,且不是一个拓扑图,也就是各个状态之间存在环,所以应该考虑最短路求解而不是DP。
将图中每个格子看成一个点,若图中两个格子之间可以相互到达,即都是空格,则在这两个点之间建立一条有向边,若是往上、下、左走,边权为 0 0 0,只有往右走,边权为 1 1 1,所以问题就转换为了从 ( r , c ) (r,c) (r,c)走到 ( i , j ) (i,j) (i,j)的最短距离。因为图中边权仅含 0 、 1 0、1 0、1,这样的最短路径可以使用双端队列BFS求解。
#include
#include
#include
#include
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 2010;
int n, m, sx, sy, X, Y;
int dist[N][N];
char g[N][N];
bool st[N][N];
void bfs() {
memset(dist, 0x3f, sizeof dist);
dist[sx][sy] = 0;
deque<PII> q;
q.push_back({sx, sy});
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (q.size()) {
auto t = q.front(); q.pop_front();
if (st[t.x][t.y]) continue;
st[t.x][t.y] = true;
for (int i = 0; i < 4; i++) {
int x = t.x + dx[i], y = t.y + dy[i];
if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] == '*') continue;
int w = 0;
if (i == 1) w = 1; // 向右走为1
if (dist[x][y] > dist[t.x][t.y] + w) {
dist[x][y] = dist[t.x][t.y] + w;
if (w) q.push_back({x, y});
else q.push_front({x, y});
}
}
}
}
int main() {
scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &X, &Y);
sx--, sy--;
for (int i = 0; i < n; i++) scanf("%s", g[i]);
bfs();
int res = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
int b = dist[i][j];
if (b <= Y && b - (j - sy) <= X)
res++;
}
printf("%d\n", res);
return 0;
}
题目链接
题目链接
题目链接
题目链接