ABC372

水一期。

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(i1,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(iw,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+wK时把 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值