ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基础课 第二讲 数据结构

2021-10-27 13:04:15  阅读:213  来源: 互联网

标签:px int 第二 signed ++ 基础课 -- 数据结构 tt


单链表

826.单链表

双链表

827.双链表

828.模拟栈

队列

829.模拟队列

单调栈

830.单调栈

处理出每个数左边最近的比它小的数,如不存在则为 -1

cin >> a[i];
while(tt && stk[tt] >= a[i]) tt--;
if(tt) cout << stk[tt];
else cout << -1;
stk[++tt] = a[i];
131.直方图中最大的矩形

为方便,在左右两边各添一个高 -1 的矩形。对每个矩形,左边第一个小于它的位置 +1 为能拓展到的最左矩形,右边第一个小于它的位置 -1 为能拓展到的最右矩形

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const signed N = 1e5+10;
int a[N], stk[N], tt, l[N], r[N];
signed main()
{
    int n; while(cin >> n && n)
    {
        for(int i = 1; i <= n; i++)
            cin >> a[i];
        tt = 0, stk[++tt] = 0, a[0] = -1;
        for(int i = 1; i <= n; i++)
        {
            while(a[stk[tt]] >= a[i]) tt--;
            l[i] = stk[tt] + 1;
            stk[++tt] = i;
        }
        tt = 0, stk[++tt] = n+1, a[n+1] = -1;
        for(int i = n; i >= 1; i--)
        {
            while(a[stk[tt]] >= a[i]) tt--;
            r[i] = stk[tt] - 1;
            stk[++tt] = i;
        }
        ll ans = 0;
        for(int i = 1; i <= n; i++)
            ans = max(ans, (ll)a[i]*(r[i]-l[i]+1));
        cout << ans << '\n';
    }

    return 0;
}

单调队列

154.滑动窗口
#include <bits/stdc++.h>
using namespace std;
const signed N = 1e6+10;
int a[N], q[N];
signed main()
{
    int n, k; cin >> n >> k;
    for(int i = 0; i < n; i++) cin >> a[i];
    int hh = 0, tt = -1;
    for(int i = 0; i < n; i++)
    { //找最小值
        if(hh<=tt && i-k+1>q[hh]) hh++;
        while(hh<=tt && a[q[tt]]>=a[i]) tt--;
        q[++tt] = i;
        if(i >= k-1) cout << a[q[hh]] << ' ';
    }
    cout << '\n';
    hh = 0, tt = -1;
    for(int i = 0; i < n; i++)
    { //找最大值
        if(hh<=tt && i-k+1>q[hh]) hh++;
        while(hh<=tt && a[q[tt]]<=a[i]) tt--;
        q[++tt] = i;
        if(i >= k-1) cout << a[q[hh]] << ' ';
    }

    return 0;
}

KMP

831.KMP字符串

求出模板串P在模式串S中所有出现的位置的起始下标

#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 1000010;

int n, m;
char p[N], s[M];
int ne[N];

int main()
{ //字符串都从1开始
    cin >> n >> p + 1 >> m >> s + 1;
    //求ne数组, ne[1] = 0
    for(int i = 2, j = 0; i <= n; i ++ )
    {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if(p[i] == p[j + 1]) j++;
        ne[i] = j;
    }
    //kmp
    for(int i = 1, j = 0; i <= m; i ++ )
    {
        while(j && s[i] != p[j + 1]) j = ne[j];
        if(s[i] == p[j + 1]) j ++;
        if(j == n)//成功匹配
        {
            printf("%d ",i - n);
            j = ne[j]; //再次缩短长度进行下一次的匹配
        }
    }

    return 0;
}

Trie

835.Trie字符串统计
143.最大异或对

在数组中选两个进行异或运算的最大值

#include <bits/stdc++.h>
using namespace std;
const signed N = 1e5+10;
int ans, tr[31*N][2], idx;
void ins(int x)
{
    int p = 0;
    for(int i = 30; i >= 0; i--)
    {
        int u = x>>i&1;
        if(!tr[p][u]) tr[p][u] = ++idx;
        p = tr[p][u];
    }
}

signed main()
{
    int n; cin >> n;
    while(n--)
    {
        int x; cin >> x;
        ins(x);
        int p = 0, res = 0;
        for(int i = 30; i >= 0; i--)
        {
            int u = x>>i&1;
            if(tr[p][u^1]) //也可写!u
                res |= (1<<i), p = tr[p][u^1];
            else
                p = tr[p][u];
        }
        ans = max(ans, res);
    }
    cout << ans;

    return 0;
}

并查集

836.合并集合
837.连通块中点的数量

维护每棵树的点数的并查集

240.食物链(真妙啊)

维护到祖宗距离(这题是距离%3)的并查集

#include <bits/stdc++.h>
using namespace std;
const signed N = 50010;
int p[N], d[N];
int find(int x)
{
    if(p[x] != x)
    {
        int t = find(p[x]);
        d[x] += d[p[x]];
        p[x] = t;
    }
    return p[x];
}
signed main()
{
    int n, m, ans = 0; cin >> n >> m;
    for(int i = 1; i <= n; i++) p[i] = i;
    while(m--)
    {
        int t, x, y; cin >> t >> x >> y;
        if(x > n || y > n) ans++;
        else
        {
            int px = find(x), py = find(y);
            if(t == 1)
            {
                if(px == py && (d[x] - d[y]) % 3) ans++;
                else if(px != py)
                {
                    p[px] = p[y];
                    d[px] = d[y] - d[x];
                }
            }
            else
            {
                if(px == py && (d[x] - d[y] - 1) % 3) ans++;
                else if(px != py)
                {
                    p[px] = p[y];
                    d[px] = d[y] + 1 - d[x];
                }
            }
        }
    }
    cout << ans;

    return 0;
}

\(O(n)\) 建堆:对 i=n/2i=1 进行 down(i) 操作

838.堆排序

从小到大输出 m 个数

#include <bits/stdc++.h>
using namespace std;
const signed N = 1e5+10;
int h[N], n;
void down(int u)
{
    int t = u;
    if (u * 2 <= n && h[u * 2] < h[t]) t = u * 2;
    if (u * 2 + 1 <= n && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    if (u != t)
    {
        swap(h[u], h[t]);
        down(t);
    }
}
signed main()
{
    int m; cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> h[i];
    for(int i = n/2; i; i--) down(i);
    while(m--)
    {
        cout << h[1] << ' ';
        h[1] = h[n--];
        down(1);
    }

    return 0;
}

839.模拟堆

哈希表

N 一般取hash数组长度的第一个质数如100003、200003

//找质数
for(int i = N; i++)
{
    bool flag = 1;
    for(int j = 2; j*j<=i;j++) if(i%j==0)
    {
        flag = 0; break;
    }
    if(flag)
    {
        cout << i; break;
    }
}

开放寻址法hash数组的长度要开题目数据范围的两到三倍

840.模拟散列表
//题目范围100000,开放寻址法
const int N = 200003, null = 0x3f3f3f3f;
int h[N];
int find(int x) //找x的位置
{
    int k = (x % N + N) % N;
    while(h[k] != null && h[k] != x)
    {
        k++;
        if(k == N) k = 0;
    }
    return k;
}
int main()
{
    memset(h, 0x3f, sizeof h);
    h[find(x)] = x; //插入x
    h[find(x)] != null; //存在x
}
841.字符串哈希

把字符串看成一个 p 进制数(左边是高位),转成10进制并 mod Q

经验上 p 取 131 或 13331,Q 取 2e64(用 ull 自然溢出即可)

注意不能映射成 0, 'A' 要看成 1 而不是 0,否则会误判 "A" == "AA"。所以直接用 ascii 码算就行了,不用减去 'A' 之类的

h[i] = h[i-1]*p + str[i]

[L,R] 的哈希值为 h[R]-h[L]*p^(R-L+1)

标签:px,int,第二,signed,++,基础课,--,数据结构,tt
来源: https://www.cnblogs.com/wushansinger/p/15470085.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有