【算法提高——第四讲】高级数据结构(3)

简介: 【算法提高——第四讲】高级数据结构(3)

4.5 平衡树

4.5.1 253. 普通平衡树

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=100010,INF=1e9;
int n;
struct Node
{
    int l,r;
    int key,val;
    int cnt,sz;
}tr[N];
int root,idx;
void pushup(int p)
{
    tr[p].sz=tr[tr[p].l].sz+tr[tr[p].r].sz+tr[p].cnt;
}
int get_node(int key)   //创建新的节点
{
    tr[++idx].key=key;
    tr[idx].val=rand();
    tr[idx].cnt=tr[idx].sz=1;
    return idx;
}
void zig(int &p)    // 右旋
{
    int q=tr[p].l;
    tr[p].l=tr[q].r,tr[q].r=p,p=q;
    pushup(tr[p].r),pushup(p);
}
void zag(int &p)    // 左旋
{
    int q=tr[p].r;
    tr[p].r=tr[q].l,tr[q].l=p,p=q;
    pushup(tr[p].l),pushup(p);
}
void build()
{
    get_node(-INF),get_node(INF);
    root=1,tr[1].r=2;
    pushup(root);
    if(tr[1].val<tr[2].val) zag(root);
}
void my_insert(int &p,int key)
{
    if(!p) p=get_node(key);
    else if(tr[p].key==key) tr[p].cnt++;
    else if(tr[p].key>key)
    {
        my_insert(tr[p].l,key);
        if(tr[tr[p].l].val>tr[p].val) zig(p);
    }
    else
    {
        my_insert(tr[p].r,key);
        if(tr[tr[p].r].val>tr[p].val) zag(p);
    }
    pushup(p);
}
void my_remove(int &p,int key)
{
    if(!p) return;
    if(tr[p].key==key)
    {
        if(tr[p].cnt>1) tr[p].cnt--;
        else if(tr[p].l||tr[p].r)
        {
            if(!tr[p].r||tr[tr[p].l].val>tr[tr[p].r].val)
            {
                zig(p);
                my_remove(tr[p].r,key);
            }
            else
            {
                zag(p);
                my_remove(tr[p].l,key);
            }
        }
        else
            p=0;
    }
    else if(tr[p].key>key) my_remove(tr[p].l,key);
    else my_remove(tr[p].r,key);
    pushup(p);
}
int get_rank_by_key(int p,int key)  // 通过数值找排名
{
    if(!p) return 0;    // 本题中不会发生此情况
    if(tr[p].key==key) return tr[tr[p].l].sz+1;
    if(tr[p].key>key) return get_rank_by_key(tr[p].l,key);
    return tr[tr[p].l].sz+tr[p].cnt+get_rank_by_key(tr[p].r,key);
}
int get_key_by_rank(int p,int rk) // 通过排名找数值rk:rank
{
    if(!p) return INF;  // 本题中不会发生此情况
    if(tr[tr[p].l].sz>=rk) return get_key_by_rank(tr[p].l,rk);
    if(tr[tr[p].l].sz+tr[p].cnt>=rk) return tr[p].key;
    return get_key_by_rank(tr[p].r,rk-tr[tr[p].l].sz-tr[p].cnt);
}
int get_prev(int p,int key)     // 找到严格小于key的最大数
{
    if(!p) return -INF;
    if(tr[p].key>=key) return get_prev(tr[p].l,key);
    return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int p,int key)     // 找到严格大于key的最小数
{
    if(!p) return INF;
    if(tr[p].key<=key) return get_next(tr[p].r,key);
    return min(tr[p].key,get_next(tr[p].l,key));
}
int main()
{
    build();
    cin>>n;
    while(n--)
    {
        int op,x;
        cin>>op>>x;
        if(op==1) my_insert(root,x);
        else if(op==2) my_remove(root,x);
        else if(op==3) cout<<get_rank_by_key(root,x)-1<<endl;
        else if(op==4) cout<<get_key_by_rank(root,x+1)<<endl;
        else if(op==5) cout<<get_prev(root,x)<<endl;
        else cout<<get_next(root,x)<<endl;
    }
    return 0;
}

4.5.2 265. 营业额统计

image.png


代码:


/* Treep
#include<bits/stdc++.h>
using namespace std;
const int N=1000010,INF=1e9;
int n;
struct Node
{
    int l,r;
    int key,val;
    int cnt,sz;
}tr[N];
int root,idx;
void pushup(int p)
{
    tr[p].sz=tr[tr[p].l].sz+tr[tr[p].r].sz+tr[p].cnt;
}
int get_node(int key)   //创建新的节点
{
    tr[++idx].key=key;
    tr[idx].val=rand();
    tr[idx].cnt=tr[idx].sz=1;
    return idx;
}
void zig(int &p)    // 右旋
{
    int q=tr[p].l;
    tr[p].l=tr[q].r,tr[q].r=p,p=q;
    pushup(tr[p].r),pushup(p);
}
void zag(int &p)    // 左旋
{
    int q=tr[p].r;
    tr[p].r=tr[q].l,tr[q].l=p,p=q;
    pushup(tr[p].l),pushup(p);
}
void build()
{
    get_node(-INF),get_node(INF);
    root=1,tr[1].r=2;
    pushup(root);
    if(tr[1].val<tr[2].val) zag(root);
}
void my_insert(int &p,int key)
{
    if(!p) p=get_node(key);
    else if(tr[p].key==key) tr[p].cnt++;
    else if(tr[p].key>key)
    {
        my_insert(tr[p].l,key);
        if(tr[tr[p].l].val>tr[p].val) zig(p);
    }
    else
    {
        my_insert(tr[p].r,key);
        if(tr[tr[p].r].val>tr[p].val) zag(p);
    }
    pushup(p);
}
int get_prev(int p,int key)     // 找到严格小于等于key的最大数
{
    if(!p) return -INF;
    if(tr[p].key>key) return get_prev(tr[p].l,key);
    return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int p,int key)     // 找到严格大于等于key的最小数
{
    if(!p) return INF;
    if(tr[p].key<key) return get_next(tr[p].r,key);
    return min(tr[p].key,get_next(tr[p].l,key));
}
int main()
{
    ios::sync_with_stdio(0);
    build();
    cin>>n;
    int res=0;
    for(int i=1;i<=n;i++)
    {
        int key;
        cin>>key;
        if(i==1) res+=key;
        else
        {
            int aj1=get_prev(root,key),aj2=get_next(root,key);
            if(aj1==-INF) aj1=INF;
            int aj=min(abs(aj1-key),abs(aj2-key));
            res+=aj;
        }
        my_insert(root,key);
    }
    cout<<res<<endl;
    return 0;
}
*/
//STL set lower_bound >=
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n;
set<int> st;
int main()
{
    cin>>n;
    int res=0;
    set<int>::iterator it;
    st.insert(-INF);
    st.insert(INF);
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        if(i==0)
            res+=x;
        else
        {
            int aj1,aj2;
            it=st.lower_bound(x);
            aj1=*it;
            aj2=*(--it);
            res+=min(aj1-x,x-aj2);
        }
        st.insert(x);
    }
    cout<<res<<endl;
    return 0;
}

4.6 AC自动机

4.6.1 1282. 搜索关键词

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=10010,S=55,M=1000010;
int n;
int tr[N*S][26],cnt[N*S],idx;
char str[M];
int q[N*S],ne[N*S];
void my_insert()    //trie中插入节点
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int t=str[i]-'a';
        if(!tr[p][t]) tr[p][t]=++idx;
        p=tr[p][t];
    }
    cnt[p]++;
}
void build()
{
    queue<int> q;
    for(int i=0;i<26;i++)
    {
        if(tr[0][i])
            q.push(tr[0][i]);
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            int p=tr[t][i];
            if(!p) tr[t][i]=tr[ne[t]][i];
            else
            {
                ne[p]=tr[ne[t]][i];
                q.push(p);
            }
        }
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(tr,0,sizeof tr);
        memset(cnt,0,sizeof cnt);
        memset(ne,0,sizeof ne);
        idx=0;
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>str;
            my_insert();
        }
        build();
        cin>>str;
        int res=0;
        for(int i=0,j=0;str[i];i++)
        {
            int t=str[i]-'a';
            j=tr[j][t];
            int p=j;
            while(p)
            {
                res+=cnt[p];
                cnt[p]=0;
                p=ne[p];
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

4.6.2 1285. 单词

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int n;
int tr[N][26],f[N],idx;
int ne[N];
char str[N];
int id[210];
vector<int> seq;
void my_insert(int x)
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int t=str[i]-'a';
        if(!tr[p][t]) tr[p][t]=++idx;
        p=tr[p][t];
        f[p]++;
    }
    id[x]=p;
}
void build()
{
    queue<int> q;
    for(int i=0;i<26;i++)
    {
        if(tr[0][i])
        {
            q.push(tr[0][i]);
            seq.push_back(tr[0][i]);
        }
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            int &p=tr[t][i];
            if(!p) p=tr[ne[t]][i];
            else
            {
                ne[p]=tr[ne[t]][i];
                q.push(p);
                seq.push_back(p);
            }
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>str;
        my_insert(i);
    }
    build();
    for(int i=seq.size()-1;i>=0;i--) f[ne[seq[i]]]+=f[seq[i]];
    for(int i=0;i<n;i++)
        cout<<f[id[i]]<<endl;
    return 0;
}

相关文章
|
20天前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
14 0
|
9天前
|
机器学习/深度学习 存储 算法
【数据结构】算法的复杂度
算法的时间复杂度和空间复杂度
16 1
【数据结构】算法的复杂度
|
2天前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
9 1
|
5天前
|
存储 算法 调度
惊呆了!Python高级数据结构堆与优先队列,竟然能这样优化你的程序性能!
【7月更文挑战第10天】Python的heapq模块实现了堆和优先队列,提供heappush和heappop等函数,支持O(log n)时间复杂度的操作。优先队列常用于任务调度和图算法,优化性能。例如,Dijkstra算法利用最小堆加速路径查找。堆通过列表存储,内存效率高。示例展示了添加、弹出和自定义优先级元素。使用堆优化程序,提升效率。
15 2
|
20天前
|
算法 分布式数据库
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
12 1
|
7天前
|
算法 安全 调度
逆天改命!Python高级数据结构堆(Heap)与优先队列,让你的算法效率飙升至宇宙级!
【7月更文挑战第8天】Python的heapq模块和queue.PriorityQueue实现了堆和优先队列,提供高效算法解决方案。堆用于Dijkstra算法求解最短路径,例如在图论问题中;PriorityQueue则在多线程下载管理中确保高优先级任务优先执行。这两个数据结构提升效率,简化代码,是编程中的强大工具。
10 0
|
7天前
|
存储 算法 安全
解锁Python高级数据结构新姿势:堆与优先队列的实战演练,让你的代码更优雅!
【7月更文挑战第8天】Python的`heapq`模块和`queue.PriorityQueue`提供堆与优先队列功能,用于高效数据管理。堆是完全二叉树,`heapq`实现最小堆,常用于任务调度,如按优先级执行任务。当需要线程安全且更复杂操作时,`queue.PriorityQueue`成为优选,例如在管理网络请求时按优先级处理。这两个数据结构能提升代码效率和可读性。
|
7天前
|
算法 搜索推荐 Java
在Java中实现高效的算法与数据结构
在Java中实现高效的算法与数据结构
|
17天前
|
存储 算法 调度
算法与数据结构-栈篇
算法与数据结构-栈篇
14 0
|
18天前
|
人工智能 算法
程序技术好文:算法与数据结构
程序技术好文:算法与数据结构