代码源数据结构初级刷题(自用)

1. 栈

  • 103 出栈序列判断
点击查看代码
const int N = 2e5 + 10;
int n, top, stk[N];

void solve() {
    scanf("%d", &n);
    top = 0;
    int x = 0;
    for (int i = 1; i <= n; i ++) {
        int t; scanf("%d", &t);
        if (stk[top] != t) {
            for (int j = x + 1; j <= t; j ++) {
                stk[++ top] = j;
                printf("push %d\n", j);
            }
            x = t;
            printf("pop\n");
            top --;
        } else {
            top --;
            printf("pop\n");
        }
    }
}
  • 104 括号序列

    容易漏掉一种左括号没有匹配完的情况
点击查看代码
const int N = 2e5 + 10;
int n, top;
char stk[N];

void solve() {
    scanf("%d", &n);
    if (n & 1) {
        cout << "No" << endl;   
        return ;
    }
    top = 0;
    for (int i = 1; i <= n; i ++) {
        char ch; cin >> ch;
        if (ch == '(' || ch == '[') stk[++ top] = ch;
        else {
            if (ch == ')') {
                if (top == 0) {
                    cout << "No" << endl;
                    return ;
                }
                if (stk[top] == '(') top --;
                else {
                    cout << "No" << endl;
                    return ;
                }
            } else {
                if (top == 0) {
                    cout << "No" << endl;
                    return ;
                }
                if (stk[top] == '[') top --;
                else {
                    cout << "No" << endl;
                    return ;
                }
            }
        }
    }
    if (top != 0) {
        cout << "No" << endl;
        return ;
    }
    cout << "Yes" << endl;
}
  • 105 字符串处理1
点击查看代码
const int N = 2e5 + 10;
int n, top;
pair<char, int> stk[N];
bool st[N];

void solve() {
    scanf("%d", &n);
    string s; cin >> s;
    for (int i = 0; i < n; i ++) {
        if (top == 0 || stk[top].fi != s[i]) {
            stk[++ top] = {s[i], i};
            continue;
        }
        if (stk[top].fi == s[i]) {
            st[stk[top].sc] = true;
            st[i] = true;
            top --;
        }
    }
    for (int i = 0; i < n; i ++) {
        if (!st[i]) cout << s[i];
    }
    cout << endl;
}
  • 106 字符串处理2
点击查看代码
const int N = 2e5 + 10;
int n, top;
pair<char, int> stk[N];
bool st[N];

void solve() {
    scanf("%d", &n);
    string s; cin >> s;
    for (int i = 0; i < n; i ++) {
        if (s[i] >= 'A' && s[i] <= 'Z') {
            if (top == 0 || stk[top].fi != s[i] - 'A' + 'a') {
                stk[++ top] = {s[i], i};
                continue;
            }
            if (stk[top].fi == s[i] - 'A' + 'a') {
                st[stk[top].sc] = true;
                st[i] = true;
                top --;
            }
        } else {
            if (top == 0 || stk[top].fi != s[i] - 'a' + 'A') {
                stk[++ top] = {s[i], i};
                continue;
            }
            if (stk[top].fi == s[i] - 'a' + 'A') {
                st[stk[top].sc] = true;
                st[i] = true;
                top --;
            }
        }
    }
    for (int i = 1; i <= top; i ++) {
        cout << stk[i].fi;
    }
    cout << endl;
}
  • 107 出栈序列
点击查看代码
int n, top;
stack<int> stk;
vector<int> v;
int nw;
void dfs() {
    if (v.size() == n) {
        for (auto x : v) 
            printf("%d ", x);
        printf("\n");
        return ;
    }
    if (!stk.empty()) {
        v.push_back(stk.top());
        stk.pop();
        dfs();
        stk.push(v.back());
        v.pop_back();
    }
    if (nw < n) {
        nw ++;
        stk.push(nw);
        dfs();
        stk.pop();
        nw --;
    }
}

void solve() {
    scanf("%d", &n);
    nw = 0;
    dfs();
    return ;
}

2.队列

  • 203 数字统计
点击查看代码
int n, q[N], hh, tt;

void solve() {
    cin >> n;
    hh = 0;
    tt = -1;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        while (q[hh] + 5 < x && hh <= tt) hh ++;
        //cout << hh <<" ' " << tt << endl;
        q[++ tt] = x;
        cout << tt - hh << ' ';
    }
    return ;
}
  • 204排队买票
点击查看代码
const int N = 1e6 + 10;
int n, hh, tt;
PII q[N];
int ans[N];

void solve() {
    cin >> n;
    hh = 0;
    tt = -1;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        q[++ tt] = {x, i};
    }
    int t = 0;
    while (true) {
        PII x = q[hh ++];
        x.fi --;
        t ++;
        if (x.fi == 0) {
            ans[x.sc] = t;
            if (hh > tt) break;
            else continue;
        } 
        else {
            q[++ tt] = x;
        }
    }
    for (int i = 1; i <= n; i ++) 
        cout << ans[i] << ' ';
    cout << endl;
    return ;
}
  • 205 约瑟夫问题
点击查看代码
const int N = 1e6 + 10;
int n, m, hh, tt;
int q[N];
int ans[N];

void solve() {
    cin >> n >> m;
    hh = 0;
    tt = -1;
    for (int i = 1; i <= n; i ++) {
        q[++ tt] = i;
    }
    int t = 0, num = 1, cn = n;
    while (true) {
        int x = q[hh ++];
        t ++;
        if (t == m) {
            t = 0;
            ans[x] = num ++;
            cn --;
            cout << x << ' ';
            if (cn == 0) break;
            continue;
        } else {
            q[++ tt] = x;
        }

    }
    return ;
}
  • 206 循环队列练习
点击查看代码
const int N = 1e6 + 10;
int n, m, hh, tt;
int q[N];
int ans[N];
int sz = 1001;
char s[20];

void solve() {
    cin >> m;
    hh = 1, tt = 0;
    while (m --) {
        scanf("%s", s);
        if (s[2] == 's') {
            int x; scanf("%d", &x);
            tt = tt % sz + 1;
            q[tt] = x;
        } else if (s[1] == 'o') {
            hh %= sz;
            hh ++;
        } else {
            int x; scanf("%d", &x);
            if (x + hh - 1 <= sz) printf("%d\n", q[hh + x - 1]);
            else printf("%d\n", q[hh + x - 1 - sz]);
        }
    }
    return ;
}

3. 树

  • 401 遍历完全二叉树
点击查看代码
struct Node{
    int l, r, fa;
} node[N];

void dfs(int id) {
    node[id].l = id * 2;
    node[id].r = id * 2 + 1;
    node[id].fa = id / 2;
    if (id >= n) return ;
    if (node[id].l <= n) dfs(node[id].l);
    if (node[id].r <= n) dfs(node[id].r);
}

void init() {
    dfs(1);
}

void preorder(int id) {
    cout << id << ' ';
    if (node[id].l <= n) preorder(node[id].l);
    if (node[id].r <= n) preorder(node[id].r);
}

void inorder(int id) {
    if (node[id].l <= n) inorder(node[id].l);
    cout << id << ' ';
    if (node[id].r <= n) inorder(node[id].r);
}

void postorder(int id) {
    if (node[id].l <= n) postorder(node[id].l);
    if (node[id].r <= n) postorder(node[id].r);
    cout << id << ' ';
}
  • 402 遍历一般二叉树
点击查看代码
const int N = 1e6 + 10;
int n, m;
int ans[N];

struct Node{
    int l, r, fa;
} node[N];

void dfs(int id) {
    node[id].l = id * 2;
    node[id].r = id * 2 + 1;
    node[id].fa = id / 2;
    if (id >= n) return ;
    if (node[id].l <= n) dfs(node[id].l);
    if (node[id].r <= n) dfs(node[id].r);
}

void init() {
    for (int i = 1; i <= n; i ++) {
        int x, y; cin >> x >> y;
        node[i].l = x, node[i].r = y;
    }
}

void preorder(int id) {
    cout << id << ' ';
    if (node[id].l <= n && node[id].l != 0) preorder(node[id].l);
    if (node[id].r <= n && node[id].r != 0) preorder(node[id].r);
}

void inorder(int id) {
    if (node[id].l <= n && node[id].l != 0) inorder(node[id].l);
    cout << id << ' ';
    if (node[id].r <= n && node[id].r != 0) inorder(node[id].r);
}

void postorder(int id) {
    if (node[id].l <= n && node[id].l != 0) postorder(node[id].l);
    if (node[id].r <= n && node[id].r != 0) postorder(node[id].r);
    cout << id << ' ';
}


void solve() {
    cin >> n;
    init();
    preorder(1);
    cout << endl;
    inorder(1);
    cout << endl;
    postorder(1);
    cout << endl;
    return ;
}
  • 403 二叉树的最近公共祖先
点击查看代码
const int N = 1e6 + 10;
int n, m;
int ans[N];

struct Node{
    int l, r, fa;
    int dep;
} node[N];

void dfs(int id) {
    if (node[id].l) {
        node[node[id].l].dep = node[id].dep + 1;
        dfs(node[id].l);
    }
    if (node[id].r) {
        node[node[id].r].dep = node[id].dep + 1;
        dfs(node[id].r);
    }
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        int x, y; cin >> x >> y;
        if (x) node[i].l = x, node[x].fa = i;
        if (y) node[i].r = y, node[y].fa = i;
    }
    node[1].dep = 1;
    dfs(1);
    int u, v; cin >> u >> v;
    if (node[u].dep < node[v].dep) swap(u, v);
    int x = node[u].dep - node[v].dep;
    for (int i = 1; i <= x; i ++) 
        u = node[u].fa;
    while (u != v) {
        u = node[u].fa;
        v = node[v].fa;
    }
    cout << u << endl;
    return ;
}

  • 404&405 二叉树子树和1&2
点击查看代码
const int N = 1e6 + 10;
int n, m;
int ans[N];

struct Node{
    int l, r, fa;
    int dep;
    ll sum;
} node[N];

void dfs(int id) {
    if (node[id].l) {
        node[node[id].l].dep = node[id].dep + 1;
        dfs(node[id].l);
        node[id].sum += node[node[id].l].sum;
    }
    if (node[id].r) {
        node[node[id].r].dep = node[id].dep + 1;
        dfs(node[id].r);
        node[id].sum += node[node[id].r].sum;
    }
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        int x, y; cin >> x >> y;
        if (x) node[i].l = x, node[x].fa = i;
        if (y) node[i].r = y, node[y].fa = i;
    }
    for (int i = 1; i <= n; i ++) {
        cin >> node[i].sum;
    }
    node[1].dep = 1;
    dfs(1);
    for (int i = 1; i <= n; i ++) 
        cout << node[i].sum << ' ';
    return ;
}
  • 406 先序中序转后序
点击查看代码
const int N = 1e6 + 10;
int n, m;
int ans[N];

int a[N], b[N], c[N];

struct Node{
    int l, r, fa;
    int dep;
    ll sum;
} node[N];

void dfs(int id) {
    if (node[id].l) {
        node[node[id].l].dep = node[id].dep + 1;
        dfs(node[id].l);
        node[id].sum += node[node[id].l].sum;
    }
    if (node[id].r) {
        node[node[id].r].dep = node[id].dep + 1;
        dfs(node[id].r);
        node[id].sum += node[node[id].r].sum;
    }
}

void transfer_to_pre(int id, int l, int r) {
    if (l > r) return ;
    int p = l;
    while (p < r && a[p] != b[id]) p ++;
    transfer_to_pre(id + 1, l, p - 1);
    transfer_to_pre(id + (p - l + 1), p + 1, r);
    cout << b[id] << ' ';
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> b[i];
    for (int i = 1; i <= n; i ++) cin >> a[i];
    transfer_to_pre(1, 1, n);
    return ;
}
  • 407 中序后序转先序
点击查看代码
const int N = 1e6 + 10;
int n, m;
int ans[N];

int a[N], b[N], c[N];

struct Node{
    int l, r, fa;
    int dep;
    ll sum;
} node[N];

void dfs(int id) {
    if (node[id].l) {
        node[node[id].l].dep = node[id].dep + 1;
        dfs(node[id].l);
        node[id].sum += node[node[id].l].sum;
    }
    if (node[id].r) {
        node[node[id].r].dep = node[id].dep + 1;
        dfs(node[id].r);
        node[id].sum += node[node[id].r].sum;
    }
}

void transfer_to_pre(int id, int l, int r) {
    if (l > r) return ;
    int p = l;
    while (p < r && a[p] != b[id]) p ++;
    cout << b[id] << ' ';
    transfer_to_pre(id - (r - p + 1), l, p - 1);
    transfer_to_pre(id - 1, p + 1, r);
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) cin >> b[i];
    transfer_to_pre(n, 1, n);
    return ;
}

4. 哈希

  • 504 构造最长回文数组
点击查看代码
const int N = 1e6 + 10;
int n, m;
map<int, int> mp;

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        mp[x] ++;
    }
    ll ans = 0;
    bool ok = false;
    for (auto x : mp) {
        if (x.sc & 1) {
            ok = true;
            ans += (x.sc - 1);
        } else {
            ans += x.sc;
        }
    }
    if (ok) ans ++;
    cout << ans << endl;
    return ;
}
  • 505 小蜗的疑问
点击查看代码
const int N = 1e6 + 10;
const int base = 31;
const int p = 9999971;
int n, m;
int ha[N], hb[N], c[N];

void solve() {
    cin >> n >> m;
    string s, t; cin >> s >> t;
    s = " " + s;
    t = " " + t;
    c[0] = 1;
    for (int i = 1; i <= 200000; i ++) 
        c[i] = c[i - 1] * base % p;
    for (int i = 1; i <= n; i ++)
        ha[i] = (ha[i - 1] * base + (s[i] - 'a')) % p;
    for (int i = 1; i <= m; i ++)
        hb[i] = (hb[i - 1] * base + (t[i] - 'a')) % p;
    int ans = 0;
    for (int i = 1; i + m - 1 <= n; i ++) 
        if ((ha[i + m - 1] - 1LL * ha[i - 1] * c[m] % p + p) % p == hb[m]) 
            ans ++;

    cout << ans << endl;
    return ;
}

5. 堆

  • 602 合并数列
点击查看代码
const int N = 1e6 + 10;
const int base = 31;
const int p = 9999971;
int n, m;

void solve() {
    cin >> n;
    priority_queue<PII, vector<PII>, greater<PII> > pq;
    for (int i = 1; i <= n; i ++) {
        int k, b; cin >> k >> b;
        pq.push({b, k});
    }
    cin >> m;
    while (m --) {
        PII now = pq.top();
        pq.pop();
        cout << now.fi << ' ';
        pq.push({now.fi + now.sc, now.sc});
    }
    return ;
}
  • 604 动态中位数
点击查看代码
void solve() {
    cin >> n;
    priority_queue<ll> pq1; //大根堆
    priority_queue<ll, vector<ll>, greater<ll> > pq2; //小根堆
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        if (pq1.empty() || x <= pq1.top()) pq1.push(x);
        else pq2.push(x);
        if (pq1.size() > (i + 1) / 2) pq2.push(pq1.top()), pq1.pop();
        if (pq2.size() > i / 2) pq1.push(pq2.top()), pq2.pop();
        if (i & 1) {
            cout << pq1.top() << endl;
        }
    }
    return ;
}

6. 单调栈单调队列

  • 701 求下一个更大数
点击查看代码
int n, m;
int a[N], ans[N];

void solve() {  
    cin >> n;
    stack<PII> stk;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        while (stk.size() && stk.top().fi < x) {
            ans[stk.top().sc] = i;
            stk.pop();
        }
        stk.push({x, i});
    }
    while (stk.size()) {
        ans[stk.top().sc] = 0;
        stk.pop();
    }
    for (int i = 1; i <= n; i ++) 
        cout << ans[i] << ' ';
    cout << endl;
    return ;
}
  • 702 最大矩形面积
点击查看代码
int n, m;
ll a[N], ans[N];
int l[N], r[N];

void solve() {  
    cin >> n;
    stack<int> stk;
    for (int i = 1; i <= n; i ++)
        cin >> a[i];
    // 求出每个数左边第一个比他小的
    for (int i = n; i >= 1; i --) {
        while (stk.size() && a[stk.top()] > a[i]) {
            l[stk.top()] = i;
            stk.pop();
        }
        stk.push(i);
    }
    while (stk.size()) {
        l[stk.top()] = 0;
        stk.pop();
    }
    // 求出每个数右边第一个比他小的
    for (int i = 1; i <= n; i ++) {
        while (stk.size() && a[stk.top()] > a[i]) {
            r[stk.top()] = i;
            stk.pop();
        }
        stk.push(i);
    }
    while (stk.size()) {
        r[stk.top()] = n + 1;
        stk.pop();
    }
    // for (int i = 1; i <= n; i ++) 
    //     cout << l[i] << ' ';
    // cout << endl;
    // for (int i = 1; i <= n; i ++)
    //     cout << r[i] << ' ';
    // cout << endl;
    ll mx = -1;
    for (int i = 1; i <= n; i ++) {
        ans[i] = (r[i] - l[i] - 1) * a[i];
        mx = max(ans[i], mx);
    }
    cout << mx << endl;
    return ;
}
  • 703 数对统计2
点击查看代码
void solve() {  
    cin >> n;
    stack<int> stk;
    int ans = 0;
    for (int i = 1; i <= n; i ++)
        cin >> a[i];
    for (int i = 1; i <= n; i ++) {
        while (stk.size() && a[stk.top()] < a[i]) {
            ans ++;
            //cout << i << endl;
            stk.pop();
        }
        if (stk.size()) ans ++;
        //cout << ans << endl;
        stk.push(i);
    }
    cout << ans << endl;
    return ;
}
  • 704 动态区间最大数
点击查看代码
const int N = 1e6 + 10;

int n, m;
int a[N], q[N];
int hh = 0, tt = -1;

void solve() {  
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        cin >> a[i];
    for (int i = 1; i <= n; i ++) {
        while (hh <= tt && a[q[tt]] <= a[i]) tt --;
        q[++ tt] = i;
        if (i - q[hh] + 1 > m) hh ++;
        if (i >= m) cout << a[q[hh]] << ' ';
    }
    return ;
}
  • 705 最大连续区间和
点击查看代码
const int N = 1e6 + 10;

int n, m, l, r;
int a[N], q[N], s[N];;
int hh = 0, tt = -1;

void solve() {  
    cin >> n >> l >> r;
    for (int i = 1; i <= n; i ++) 
        cin >> a[i];
    for (int i = 1; i <= n; i ++) 
        s[i] = s[i - 1] + a[i];
    int ans = -1 << 30, x = l; 
    for (int i = 1; i + l - 1 <= n; i ++) {
        while (x <= i + r - 1 && x <= n) {
            while (hh <= tt && s[q[tt]] <= s[x]) tt --;
            q[++ tt] = x ++;
        }
        if (q[hh] < i + l - 1) hh ++;
        ans = max(ans, s[q[hh]] - s[i - 1]);
    }
    cout << ans << endl;
    return ;
}
  • 706 覆盖
点击查看代码
const int N = 1e6 + 10;

int n, m, h;
int a[N], q1[N], q2[N];
int hh1 = 1, tt1 = 0, hh2 = 1, tt2 = 0;

void solve() {  
    cin >> n >> h;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    int j = 0, ans = 0;
    for (int i = 1; i <= n; i ++) {
        if (hh1 <= tt1 && q1[hh1] < i) hh1 ++;
        if (hh2 <= tt2 && q2[hh2] < i) hh2 ++;
        while (j <= n && (j <= i || a[q1[hh1]] - a[q2[hh2]] <= h)) {
            j ++;
            if (j > n) break;
            while (hh1 <= tt1 && a[q1[tt1]] <= a[j]) tt1 --;
            q1[++ tt1] = j;
            while (hh2 <= tt2 && a[q2[tt2]] >= a[j]) tt2 --;
            q2[++ tt2] = j;
        }
        ans = max(ans, j - i);
    }
    cout << ans << endl;
    return ;
}

7. 树

  • 801 求树上路径
点击查看代码
const int N = 1e6 + 10;

int n, m;
vector<int> edge[N];
int pre[N];

void dfs(int st, int ed, int nw, int from) {
    pre[nw] = from;
    for (auto x : edge[nw]) {
        if (x != from) {
            dfs(st, ed, x, nw);
        }
    }
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n - 1; i ++) {
        int x, y; cin >> x >> y;
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    int u, v; cin >> u >> v;
    dfs(u, v, u, -1);
    int x = v;
    vector<int> ans;
    ans.push_back(v);
    while (pre[x] != -1) {
        ans.push_back(pre[x]);
        x = pre[x];
    }
    reverse(ans.begin(), ans.end());
    for (auto x : ans)
        cout << x << ' ';
    return ;
}
  • 802 树的直径
点击查看代码
const int N = 1e6 + 10;

int n, m;
vector<int> edge[N];
int dist[N];

void dfs(int nw, int from) {
    for (auto x : edge[nw]) {
        if (x != from) {
            dist[x] = dist[nw] + 1;
            dfs(x, nw);
        }
    }
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n - 1; i ++) {
        int x, y; cin >> x >> y;
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    dist[1] = 0;
    dfs(1, -1);
    int id, mx = -1;
    for (int i = 1; i <= n; i ++) {
        if (dist[i] > mx) {
            mx = dist[i];
            id = i;
        }
    }
    memset(dist, 0, sizeof dist);
    dfs(id, -1);
    cout << *max_element(dist + 1, dist + n + 1) << endl;
    return ;
}
  • 804 最小距离和2
点击查看代码
const int N = 1e6 + 10;

int n, m;
vector<int> edges[N];
ll dist[N], sz[N], pre[N];

void calc(int nw) {
    sz[nw] = 1;
    for (auto x : edges[nw]) {
        if (x != pre[nw]) {
            pre[x] = nw;
            calc(x);
            sz[nw] += sz[x];
        }
    }
}

void dfs(int nw) {
    for (auto x : edges[nw]) {
        if (x != pre[nw]) {
            pre[x] = nw;
            dist[x] = dist[nw] + 1;
            dfs(x);
        }
    }
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n - 1; i ++) {
        int x, y; cin >> x >> y;
        edges[x].push_back(y);
        edges[y].push_back(x);
    }
    pre[1] = -1;
    calc(1);
    int id, mi = 1 << 30;
    for (int i = 1; i <= n; i ++) {
        ll f = 0;
        for (auto x : edges[i]) {
            if (x != pre[i]) {
                f = max(f, sz[x]);
            } else {
                f = max(f, n - sz[i]);
            }
        }
        if (mi > f) {
            mi = f;
            id = i;
        }
    }
    memset(pre, -1, sizeof pre);
    dist[id] = 0;
    dfs(id);
    ll ans = 0;
    for (int i = 1; i <= n; i ++) {
        ans += dist[i];
    }
    cout << ans << endl;
    return ;
}
  • 805 树上LCA1
点击查看代码
const int N = 1e6 + 10;

int n, m;
vector<int> edges[N];
int dist[N], fa[N];

void dfs(int nw) {
    for (auto x : edges[nw]) {
        dist[x] = dist[nw] + 1;
        dfs(x);
    }
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n - 1; i ++) {
        int x, y; cin >> x >> y;
        edges[x].push_back(y);
        fa[y] = x;
    }
    dist[1] = 0;
    dfs(1);
    cin >> m;
    while (m --) {
        int x, y; cin >> x >> y;
        if (dist[x] < dist[y]) swap(x, y);
        int z = dist[x] - dist[y];
        for (int i = 1; i <= z; i ++) x = fa[x];
        while (x != y) x = fa[x], y = fa[y];
        cout << x << endl;
    }
    return ;
}
  • 806 树上LCA2
点击查看代码
const int N = 1e6 + 10;

int n, m;
vector<int> edges[N];
int dist[N], fa[N][32];

void dfs(int nw) {
    for (auto x : edges[nw]) {
        dist[x] = dist[nw] + 1;
        dfs(x);
    }
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n - 1; i ++) {
        int x, y; cin >> x >> y;
        edges[x].push_back(y);
        fa[y][0] = x;
    }
    for (int j = 1; j <= 30; j ++)
        for (int i = 1; i <= n; i ++) 
            if (fa[i][j - 1]) 
                fa[i][j] = fa[fa[i][j - 1]][j - 1];
    dist[1] = 0;
    dfs(1);
    cin >> m;
    while (m --) {
        int x, y; cin >> x >> y;
        if (dist[x] < dist[y]) swap(x, y);
        int z = dist[x] - dist[y];
        for (int i = 0; i <= 30 && z; i ++, z /= 2)
            if (z & 1) {
                x = fa[x][i];
            }
        if (x == y) {
            cout << x << endl;
            continue;
        }
        for (int i = 30; i >= 0; i --)
            if (fa[x][i] != fa[y][i]) 
                x = fa[x][i], y = fa[y][i];
        cout << fa[x][0] << endl;
    }
    return ;
}

8. 字典树

  • 901 字典树例题
点击查看代码
const int N = 1e6 + 10;

int n, m;
int nxt[N][26];
bool isend[N];
int cn;

void insert(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'z'])
            nxt[nw][s[i] - 'z'] = ++ cn;
        nw = nxt[nw][s[i] - 'z'];
    }
    isend[nw] = true; 
}

bool query(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'z'])
            return false;
        nw = nxt[nw][s[i] - 'z'];
    }
    return isend[nw]; 
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        string s; cin >> s;
        insert(s);
    }
    cin >> m;
    while (m --) {
        string s; cin >> s;
        cout << query(s) << endl;
    }
    return ;
}
  • 902 前缀次数统计
点击查看代码
const int N = 1e6 + 10;

int n, m;
int nxt[N][26], sum[N];
bool isend[N];
int cn;

void insert(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a'])
            nxt[nw][s[i] - 'a'] = ++ cn;
        nw = nxt[nw][s[i] - 'a'];
        sum[nw] ++;
    }
    isend[nw] = true; 
}

bool query(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a'])
            return false;
        nw = nxt[nw][s[i] - 'a'];
    }
    return isend[nw]; 
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        string s; cin >> s;
        insert(s);
    }
    cin >> m;
    while (m --) {
        string s; cin >> s;
        int sz = s.size();
        int nw = 0;
        bool ok = true;
        for (int i = 0; i < sz && ok; i ++) {
            if (!nxt[nw][s[i] - 'a']) ok = false;
            nw = nxt[nw][s[i] - 'a'];
        }
        if (!ok) {
            cout << 0 << endl;
        } else {
            cout << sum[nw] << endl;
        }
    }
    return ;
}
  • 903 字符串排序
点击查看代码
const int N = 1e6 + 10;

int n, m;
int nxt[N][26];
bool isend[N];
int cn;
string s;

void dfs(int nw, int dep) {
    if (isend[nw]) 
        cout << s << endl;
    for (int i = 0; i < 26; i ++) {
        if (nxt[nw][i]) {
            char t = i + 'a';
            string copy = s;
            s = s + t;
            dfs(nxt[nw][i], dep + 1);
            s = copy;
        }
    }
}

void insert(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a'])
            nxt[nw][s[i] - 'a'] = ++ cn;
        nw = nxt[nw][s[i] - 'a'];
    }
    isend[nw] = true; 
}

bool query(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a'])
            return false;
        nw = nxt[nw][s[i] - 'a'];
    }
    return isend[nw]; 
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        string s; cin >> s;
        insert(s);
    }
    dfs(0, 0);
    return ;
}
  • 904 最长公共前缀问题
点击查看代码
const int N = 1e6 + 10;

int n, m;
int nxt[N][26];
bool isend[N];
int cn;
int idx[N], dep[N];
int fa[N][30];

void insert(int id, string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a']) {
            nxt[nw][s[i] - 'a'] = ++ cn;
            dep[nxt[nw][s[i] -'a']] = dep[nw] + 1;
            fa[nxt[nw][s[i] - 'a']][0] = nw;
        }
        nw = nxt[nw][s[i] - 'a'];
    }
    isend[nw] = true; 
    idx[id] = nw;
}

bool query(string s) {
    int sz = s.size();
    int nw = 0;
    for (int i = 0; i < sz; i ++) {
        if (!nxt[nw][s[i] - 'a'])
            return false;
        nw = nxt[nw][s[i] - 'a'];
    }
    return isend[nw]; 
}

void solve() {  
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        string s; cin >> s;
        insert(i, s);
    }
    for (int j = 1; j <= 20; j ++) 
        for (int i = 1; i <= cn; i ++) 
            if (fa[i][j - 1])
                fa[i][j] = fa[fa[i][j - 1]][j - 1];
    cin >> m;
    while (m --) {
        int x, y; cin >> x >> y;
        x = idx[x], y = idx[y];
        if (dep[x] < dep[y]) swap(x, y);
        int z = dep[x] - dep[y];
        for (int i = 0; i < 20 && z; i ++, z /= 2) 
            if (z & 1)
                x = fa[x][i];
        if (x == y) {
            cout << dep[x] << endl;
            continue;
        }
        for (int i = 20; i >= 0; i --) 
            if (fa[x][i] != fa[y][i]) 
                x = fa[x][i], y = fa[y][i];
        cout << dep[fa[x][0]] << endl;
    }
    return ;
}

9. 并查集

  • 1001 并查集例题
点击查看代码
const int N = 1e6 + 10;

int n, m;
int fa[N];

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

void solve() {  
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        fa[i] = i;
    while (m --) {
        char ch; 
        int x, y;
        cin >> ch >> x >> y;
        if (ch == 'M') {
            x = find(x), y = find(y);
            fa[x] = y;
        } else {
            x = find(x), y = find(y);
            if (x == y) cout << 1 << endl;
            else cout << 0 << endl;
        }
    }
    return ;
}
  • 1002 修路
点击查看代码
const int N = 1e6 + 10;

int n, m;
int fa[N];

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

void solve() {  
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        fa[i] = i;
    for (int i = 1; i <= m; i ++) {
        int x, y; cin >> x >> y;
        x = find(x), y = find(y);
        fa[x] = y;
    }
    set<int> se;
    for (int i = 1; i <= n; i ++) {
        int x = find(i);
        se.insert(x);
    }
    cout << se.size() - 1 << endl;
    return ;
}
  • 1003 行进路线
点击查看代码
const int N = 1e6 + 10;

int n, m;
int fa[N];

struct Node{
    ll x, y, r;
} node[N];

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

void solve() {  
    ll xe, ye; cin >> xe >> ye;
    cin >> n;
    node[0].x = 0, node[0].y = 0, node[0].r = 1;
    for (int i = 1; i <= n; i ++) 
        cin >> node[i].x >> node[i].y >> node[i].r;
    for (int i = 0; i <= n; i ++)
        fa[i] = i;
    for (int i = 0; i <= n; i ++) 
        for (int j = i + 1; j <= n; j ++) 
            if ((node[i].x - node[j].x) * (node[i].x - node[j].x) + 
                (node[i].y - node[j].y) * (node[i].y - node[j].y) <=
                (node[i].r + node[j].r) * (node[i].r + node[j].r)) {
                int fx = find(i), fy = find(j);
                if (fx == fy) continue;
                fa[fx] = fy;
            }
    int idx = -1;
    for (int i = 0; i <= n; i ++) {
        if ((node[i].x - xe) * (node[i].x - xe) + 
                (node[i].y - ye) * (node[i].y - ye) <=
                node[i].r * node[i].r) {
                idx = i;
            }
    }
    if (idx != -1 && find(0) == find(idx)) 
        cout << 1 << endl;
    else 
        cout << 0 << endl;
    return ;
}
posted @ 2024-02-26 20:15  ComistryMo  阅读(29)  评论(0)    收藏  举报