水一期。
A
将字符串中不是.的字符拼起来
B
给出一个整数
M
M
M
求
∑
3
A
i
=
M
\sum3^{A_i}=M
∑3Ai=M的表达形式
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int main(){
//freopen("in.txt", "r", stdin);
int m;
cin >> m;
vector<pii> t;
int i = 0;
while (m) {
t.push_back({ m % 3, i ++ });
m /= 3;
}
vi ans;
for (auto [r, c] : t) {
if (r) {
for (int j = 0; j < r; ++j) {
ans.push_back(c);
}
}
}
printf("%d\n", ans.size());
for (int i : ans) {
printf("%d ", i);
}
printf("\n");
return 0;
}
C
给定一个字符串 S S S,每次修改其中的一个字符,求修改完后整个字符串里含有 A B C ABC ABC的个数。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int main(){
//freopen("in.txt", "r", stdin);
string s;
int n, q;
cin >> n >> q;
cin >> s;
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (i >= 2 && s[i] == 'C' && s[i - 1] == 'B' && s[i - 2] == 'A') {
cnt++;
}
}
while (q--) {
int p;
char t;
cin >> p >> t;
p--;
if (s[p] == 'A') {
if (p + 2 < n && s[p + 1] == 'B' && s[p + 2] == 'C') cnt--;
}
else if (s[p] == 'B') {
if (p >= 1 && p + 1 < n && s[p - 1] == 'A' && s[p + 1] == 'C') cnt--;
}
else if (s[p] == 'C') {
if (p >= 2 && s[p - 1] == 'B' && s[p - 2] == 'A') cnt--;
}
if (t == 'A') {
if (p + 2 < n && s[p + 1] == 'B' && s[p + 2] == 'C') cnt++;
}
else if (t == 'B') {
if (p >= 1 && p + 1 < n && s[p - 1] == 'A' && s[p + 1] == 'C') cnt++;
}
else if (t == 'C') {
if (p >= 2 && s[p - 1] == 'B' && s[p - 2] == 'A') cnt++;
}
s[p] = t;
printf("%d\n", cnt);
}
return 0;
}**
D
元素互不相同的数组
a
a
a,对于每个
i
i
i求
j
j
j的个数,使得
1.
j
>
i
1. j>i
1.j>i
2.
a
[
j
]
=
m
a
x
(
a
[
i
+
1
]
,
a
[
i
+
2
]
.
.
.
a
[
j
]
)
2. a[j]=max(a[i+1],a[i+2]...a[j])
2.a[j]=max(a[i+1],a[i+2]...a[j])
单调栈。从右往左遍历
i
i
i,维护从栈顶向栈底单调递增的序列
如例子中的
21435
2 1 4 3 5
21435
遍历5:加入5,栈内元素都可以作为左边3的j
3:加入3,得到35,35都可以作为4的j
4:将3出栈(因为3不可能作为1的j),入4,得到45
1:145
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int a[200020], n;
int main(){
//freopen("in.txt", "r", stdin);
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
stack<int> st;
vi ans;
for (int i = n; i >= 1; --i) {
ans.push_back(st.size());
while (st.size() && st.top() < a[i]) {
st.pop();
}
st.push(a[i]);
}
reverse(ans.begin(), ans.end());
for (auto i : ans) {
printf("%d ", i);
}
printf("\n");
return 0;
}
E
图中
n
n
n个点,起始是互不相连通的。
依次给出一些操作:
1.连通点uv,
2.查询点u的连通子图中第k大的数。
维护并查集,在并查集的根节点里面维护不大于10的set,做并查集merge操作的时候合并set,并取出前10元素
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
set<int, greater<int>> s[200020];
int f[200020];
int n, q;
int getf(int x) {
if (x == f[x]) return x;
return f[x] = getf(f[x]);
}
int main(){
//freopen("in.txt", "r", stdin);
cin >> n >> q;
for (int i = 1; i <= n; ++i) s[i].insert(i);
for (int i = 1; i <= n; ++i) f[i] = i;
while (q--) {
int op, u, v;
cin >> op >> u >> v;
if (op == 1) {
int fu = getf(u), fv = getf(v);
if (fu == fv) continue;
f[fu] = fv;
for (auto x : s[fu]) s[fv].insert(x);
if (s[fv].size() > 11) {
auto it = s[fv].begin();
for (int i = 0; i < 10; ++i)
it++;
while (it != s[fv].end()) {
int t = *it;
it++;
s[fv].erase(t);
}
}
}
else {
int fu = getf(u);
if (v > s[fu].size()) {
printf("-1\n");
}
else {
auto it = s[fu].begin();
for (int i = 0; i < v - 1; ++i) it++;
printf("%d\n", *it);
}
}
}
return 0;
}
F
在n个点组成的环图中,加入m条边。
(
m
<
50
)
(m<50)
(m<50)
求从点1开始的路径长度为k的路径个数。
官方题解2的做法:
设
f
(
i
,
u
)
f(i,u)
f(i,u)代表路径长度为i,最后一个节点为u的路径个数
则
f
(
i
,
u
)
=
∑
f
(
i
−
1
,
v
)
f(i,u)=\sum f(i-1,v)
f(i,u)=∑f(i−1,v)其中
(
v
,
u
)
(v,u)
(v,u)有有向边。
但是这个方程复杂度不行,需要看题目给的条件优化。
假设有6个点构成环,然后1->4有边。那么23两个点对于1和4并没有实际作用,可以考虑把23两个点去掉,取而代之在14之间连一条长度为3的边。在代码里面重新建了一张图,最终的节点数<=100。
方程就变为
f
(
i
,
u
)
=
∑
f
(
i
−
w
,
v
)
f(i,u)= \sum f(i-w,v)
f(i,u)=∑f(i−w,v)
考虑到中间的23节点对于答案有作用,我们可以从前往后递推,
f
(
i
+
w
,
v
)
=
∑
f
(
i
,
u
)
f(i + w,v)=\sum f(i,u)
f(i+w,v)=∑f(i,u)如果
u
,
v
u,v
u,v的边长是
w
w
w。当
i
+
w
≥
K
i+w \geq K
i+w≥K时把
f
(
i
,
u
)
f(i,u)
f(i,u)加入到答案里面。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
vector<pii> g[200020];
set<int> s;
int n, m, K;
ll mod = 998244353;
ll f[200020][110];
struct Edge {
int u, v, w;
};
map<int, int> vhash;
int idx;
vector<Edge> e;
#define addm(x, y) (x = (x + y) % mod)
int main(){
//freopen("in.txt", "r", stdin);
cin >> n >> m >> K;
if (m == 0) {
printf("1\n");
return 0;
}
s.insert(1);
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
s.insert(u);
s.insert(v);
g[u].push_back({ v, 1 });
}
int l = -1, first = -1;
for (int i = 1; i <= n; ++i) {
if (s.count(i)) {
if (l != -1) {
g[l].push_back({ i, i - l });
}
if (first == -1) {
first = i;
}
l = i;
}
}
g[l].push_back({ first, (first + n - l) % n });
for (int i = 1; i <= n; ++i) {
for (auto [v, w] : g[i]) {
if (vhash.count(i) == 0) {
vhash[i] = ++idx;
}
if (vhash.count(v) == 0) {
vhash[v] = ++idx;
}
Edge edge({ vhash[i], vhash[v], w });
e.push_back(edge);
}
}
f[0][1] = 1;
ll ans = 0;
for (int i = 0; i < K; ++i) {
for (auto [u, v, w] : e) {
if (i + w >= K) {
addm(ans, f[i][u]);
}
else {
addm(f[i + w][v], f[i][u]);
}
}
}
printf("%lld\n", ans);
return 0;
}