码迷,mamicode.com
首页 > 编程语言 > 详细

Acwing-----算法基础课之第二讲(数据结构二)

时间:2020-09-15 20:53:33      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:父节点   com   int   并查集   --   字符串   堆排   连通块   编号   

835 Trie字符串统计

#include <iostream>
using namespace std;

const int N = 100010;
int n;
int son[N][26], cnt[N], idx; //下标是0的点既是根节点又是空结点
char str[N];

void insert(char str[]) {
    int p = 0;
    for (int i = 0; str[i]; ++i) {
        int u = str[i] - ‘a‘;
        if (!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
    cnt[p]++;
}

int query(char str[]) {
    int p = 0;
    for (int i = 0; str[i]; ++i) {
        int u = str[i] - ‘a‘;
        if (!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}

int main() {
    int n;
    cin >> n;
    while (n--) {
        char op[2];
        cin >> op >> str;
        if (op[0] == ‘I‘) insert(str);
        else cout << query(str) << endl;
    }
    return 0;
}

143.最大异或对

#include <iostream>
using namespace std;

const int N = 100010, M = 31 * N;

int n;
int a[N], son[M][2], idx;

void insert(int x) {
    int p = 0;
    for (int i = 30; i >= 0; --i) {
        int u = x >> i & 1;
        if (!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
}

int query(int x) {
    int p = 0, ans = 0;
    for (int i = 30; i >= 0; --i) {
        int u = x >> i & 1;
        if (son[p][!u]) {
            ans = ans * 2 + !u;
            p = son[p][!u];
        } else {
            p = son[p][u];
            ans = ans * 2 + u;
        }
    }
    return ans;
}

int main() {
    cin >> n;
    for (int i = 0; i < n; ++i) cin >> a[i];
    
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        insert(a[i]);
        int t = query(a[i]);
        ans = max(ans, a[i] ^ t);
    }
    cout << ans << endl;
    return 0;
}

836.合并集合

并查集: 1.将两个集合合并;

? 2.询问两个元素是否在一个集合中。

基本原理:每个集合用一棵树来表示,树根的编号就是整个集合的编号,每个节点存储它的父节点,p[x]表示它的父节点。

#include <iostream>
using namespace std;

const int N = 100010;
int n, m, p[N];

// 返回x的祖宗节点(路径压缩)
int find(int x) {
    if (p[x] != x)  p[x] = find(p[x]);
    return p[x];
}

int main() {
    cin >> n >> m;
    
    for (int i = 1; i <= n; ++i) p[i] = i;
    while (m--) {
        char op[2];
        int a, b;
        cin >> op >> a >> b;
        if (op[0] == ‘M‘) p[find(a)] = find(b);
        else {
            if (find(a) == find(b)) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

837.连通块中点的数量

#include <iostream>
using namespace std;

const int N = 100010;
int n, m;
int p[N], sz[N];

int find(int x) {
    if (x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main() {
    cin >> n >> m;
    
    for (int i = 1; i <= n; ++i) p[i] = i, sz[i] = 1;
    
    while (m--) {
        char op[5];
        int a, b;
        cin >> op;
        
        if (op[0] == ‘C‘) {
            cin >> a >> b;
            if (find(a) == find(b)) continue;
            sz[find(b)] += sz[find(a)];
            p[find(a)] = find(b);
        }
        else if (op[1] == ‘1‘) {
            cin >> a >> b;
            if (find(a) == find(b)) puts("Yes");
            else puts("No");
        } else {
            cin >> a;
            cout << sz[find(a)] << endl;
        }
    }
    return 0;
}

838.堆排序

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;
int n, m, h[N], sz;

void down(int u) {
    int t = u;
    if (u * 2 <= sz && h[u * 2] < h[t]) t = u * 2;
    if (u * 2 + 1 <= sz && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    if (u != t) {
        swap(h[u], h[t]);
        down(t);
    }
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) cin >> h[i];
    sz = n;
    
    for (int i = n / 2; i; --i) down(i);
    while (m--) {
        cout << h[1] << " ";
        h[1] = h[sz--];
        down(1);
    }
    return 0;
}

839.模拟堆

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

const int N = 100010;

int n, m, ph[N], hp[N], h[N], sz;

void heap_swap(int a, int b) {
    swap(ph[hp[a]], ph[hp[b]]);
    swap(hp[a], hp[b]);
    swap(h[a], h[b]);
}

void down(int u) {
    int t = u;
    if (u * 2 <= sz && h[u * 2] < h[t]) t = u * 2;
    if (u * 2 + 1 <= sz && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    if (u != t) {
        heap_swap(u, t);
        down(t);
    }
}

void up(int u) {
    while (u / 2 && h[u / 2] > h[u]) {
        heap_swap(u / 2, u);
        u /= 2;
    }
} 

int main() {
    cin >> n;
    while (n --) {
        char op[10];
        int k, x;
        cin >> op;
        
        if (!strcmp(op, "I")) {
            cin >> x;
            sz++;
            m++;
            ph[m] = sz, hp[sz] = m;
            h[sz] = x;
            up(sz);
        } else if (!strcmp(op, "PM")) cout << h[1] << endl;
        else if (!strcmp(op, "DM")) {
            heap_swap(1, sz--);
            down(1);
        } else if (!strcmp(op, "D")) {
            cin >> k;
            k = ph[k];
            heap_swap(k, sz);
            sz--;
            down(k), up(k);
        } else {
            cin >> k >> x;
            k = ph[k];
            h[k] = x;
            down(k), up(k);
        }
    }
    return 0;
}

Acwing-----算法基础课之第二讲(数据结构二)

标签:父节点   com   int   并查集   --   字符串   堆排   连通块   编号   

原文地址:https://www.cnblogs.com/clown9804/p/13598659.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!