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

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

4.1 并查集

4.1.1 1250. 格子游戏

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=40010;
int n,m;
int p[N];
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<=N;i++) p[i]=i;
    bool success=false;
    for(int i=0;i<m;i++)
    {
        int x,y;
        char c;
        cin>>x>>y>>c;
        int a=(x-1)*n+y-1;
        int b=a;
        if(c=='R')
        {
            b++;
        }
        else
            b+=n;
        int pa=findP(a),pb=findP(b);
        if(pa==pb)
        {
            cout<<i+1<<endl;
            success=true;
            break;
        }
        else
            p[pa]=pb;
    }
    if(!success)
        cout<<"draw"<<endl;
    return 0;
}

4.1.2 1252. 搭配购买

image.png


代码:


#include<bits/stdc++.h> //y总的
using namespace std;
const int N = 10010;
int n, m, vol;
int v[N], w[N];
int p[N];
int f[N];
int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
int main()
{
    cin >> n >> m >> vol;
    for (int i = 1; i <= n; i ++ ) p[i] = i;
    for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
    while (m -- )
    {
        int a, b;
        cin >> a >> b;
        int pa = find(a), pb = find(b);
        if (pa != pb)
        {
            v[pb] += v[pa];
            w[pb] += w[pa];
            p[pa] = pb;
        }
    }
    // 01背包
    for (int i = 1; i <= n; i ++ )
        if (p[i] == i)
            for (int j = vol; j >= v[i]; j -- )
                f[j] = max(f[j], f[j - v[i]] + w[i]);
    cout << f[vol] << endl;
    return 0;
}
/* 自己写的
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int n,m,w;
map<int,pair<int,int> > mp;
int money[N],value[N];
int cnt;
int M[N],V[N];
int dp[N];
int p[N];
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m>>w;
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=1;i<=n;i++)
    {
        cin>>money[i]>>value[i];
    }
    for(int i=0;i<m;i++)
    {
        int a,b;
        cin>>a>>b;
        p[findP(a)]=findP(b);
    }
    for(int i=1;i<=n;i++)
    {
        int pa=findP(i);
        mp[pa].first+=money[i];
        mp[pa].second+=value[i];
    }
    for(map<int,pair<int,int> >::iterator it=mp.begin();it!=mp.end();it++)
    {
        cnt++;
        M[cnt]=it->second.first;
        V[cnt]=it->second.second;
    }
    for(int i=1;i<=cnt;i++)
    {
        for(int j=w;j>=M[i];j--)
        {
                dp[j]=max(dp[j],dp[j-M[i]]+V[i]);
        }
    }
    cout<<dp[w];
    return 0;
}
*/

4.1.3 237. 程序自动分析

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int cnt;
struct Node{
    int a,b,c;
}op[100010];
unordered_map<int,int> mp;
int p[N];
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        cnt=1;
        mp.clear();
        for(int i=1;i<=N;i++) p[i]=i;
        for(int i=1;i<=n;i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            if(mp.count(a)==0)
                mp[a]=cnt++;
            if(mp.count(b)==0)
                mp[b]=cnt++;
            op[i].a=a,op[i].b=b,op[i].c=c;
        }
        for(int i=1;i<=n;i++)
        {
            int a=op[i].a,b=op[i].b,c=op[i].c;
            if(c==1)
            {
                p[findP(mp[a])]=findP(mp[b]);
            }
        }
        bool success=true;
        for(int i=1;i<=n;i++)
        {
            int a=op[i].a,b=op[i].b,c=op[i].c;
            if(c==0)
            {
                if(findP(mp[a])==findP(mp[b]))
                {
                    success=false;
                    break;
                }
            }
        }
        if(success) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

4.1.4 239. 奇偶游戏

image.png


代码:


#include<bits/stdc++.h>     //带边权并查集
using namespace std;
const int N=20010;
int n,m;
int p[N],d[N];
map<int,int> S;
int get(int x)
{
    if(S.count(x)==0) S[x]=++n;
    return S[x];
}
int findP(int x)
{
    if(p[x]!=x)
    {
        int root=findP(p[x]);
        d[x]^=d[p[x]];
        p[x]=root;
    }
    return p[x];
}
int main()
{
    cin>>n>>m;
    n=0;
    for(int i=0;i<N;i++) p[i]=i;
    int res=m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        string type;
        cin>>a>>b>>type;
        a=get(a-1),b=get(b);
        int t=0;
        if(type=="odd") t=1;
        int pa=findP(a),pb=findP(b);
        if(pa==pb)
        {
            if(d[a]^d[b]!=t)
            {
                res=i-1;
                break;
            }
        }
        else
        {
            p[pa]=pb;
            d[pa]=d[a]^d[b]^t;
        }
    }
    cout<<res<<endl;
    return 0;
}
/* 扩展域
#include<bits/stdc++.h>
using namespace std;
const int N=40010,base=N/2;
int n,m;
int p[N],d[N];
map<int,int> S;
int get(int x)
{
    if(S.count(x)==0) S[x]=++n;
    return S[x];
}
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m;
    n=0;
    for(int i=0;i<N;i++) p[i]=i;
    int res=m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        string type;
        cin>>a>>b>>type;
        a=get(a-1),b=get(b);
        if(type=="even")
        {
            if(findP(a+base)==findP(b))
            {
                res=i-1;
                break;
            }
            p[findP(a)]=findP(b);
            p[findP(a+base)]=findP(b+base);
        }
        else
        {
            if(findP(a)==findP(b))
            {
                res=i-1;
                break;
            }
            p[findP(a)]=findP(b+base);
            p[findP(a+base)]=findP(b);
        }
    }
    cout<<res<<endl;
    return 0;
}
*/

4.1.5 238. 银河英雄传说

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=30010;
int n;
int p[N],sz[N],d[N];
int findP(int x)
{
    if(p[x]!=x)
    {
        int root=findP(p[x]);
        d[x]+=d[p[x]];
        p[x]=root;
    }
    return p[x];
}
int main()
{
    cin>>n;
    for(int i=1;i<=N;i++)
    {
        p[i]=i;
        sz[i]=1;
    }
    for(int i=0;i<n;i++)
    {
        string type;
        int a,b;
        cin>>type>>a>>b;
        int pa=findP(a),pb=findP(b);
        if(type=="M")
        {
            d[pa]=sz[pb];
            sz[pb]+=sz[pa];
            p[pa]=pb;
        }
        else
        {
            if(pa!=pb)
                cout<<-1<<endl;
            else
                cout<<max(0,abs(d[a]-d[b])-1)<<endl;
        }
    }
    return 0;
}

4.2 树状数组

4.2.1 241. 楼兰图腾

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200010;
int n;
int a[N],tr[N];
int big[N],little[N];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i))  //从x开始
        tr[i]+=c;
}
int sum(int x)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))
        res+=tr[i];
    return res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        int y=a[i];
        big[i]=sum(n)-sum(y);
        little[i]=sum(y-1);
        add(y,1);
    }
    memset(tr,0,sizeof tr);
    LL res1=0,res2=0;
    for(int i=n;i>=1;i--)
    {
        int y=a[i];
        res1+=big[i]*(LL)(sum(n)-sum(y));
        res2+=little[i]*(LL)sum(y-1);
        add(y,1);
    }
    cout<<res1<<" "<<res2<<endl;
    return 0;
}

4.2.2 242. 一个简单的整数问题

image.png


代码:


#include<bits/stdc++.h> //差分,树状数组综合应用
using namespace std;
const int N=100010;
int n,m;
int a[N];
int b[N];   //差分数组
int tr[N];  //差分数组的树状数组
void myinsert(int l,int r,int c)    //差分
{
    b[l]+=c,b[r+1]-=c;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i))  //从x开始
        tr[i]+=c;
}
int sum(int x)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))
        res+=tr[i];
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
        myinsert(i,i,a[i]);
    for(int i=1;i<=n;i++)
        add(i,b[i]);
    while(m--)
    {
        string op;
        cin>>op;
        if(op=="Q")
        {
            int x;
            cin>>x;
            cout<<sum(x)<<endl;
        }
        else
        {
            int l,r,c;
            cin>>l>>r>>c;
            add(l,c),add(r+1,-c);
        }
    }
    return 0;
}

4.2.3 243. 一个简单的整数问题2

image.png


代码:


#include<bits/stdc++.h> //差分,树状数组综合应用
using namespace std;
typedef long long LL;
const int N=100010;
int n,m;
int a[N];
LL tr_b[N];  //差分数组b[i]的树状数组
LL tr_bi[N]; //差分数组b[i]*i的树状数组
int lowbit(int x)
{
    return x&(-x);
}
void add(LL tr[],int x,LL c)
{
    for(int i=x;i<=n;i+=lowbit(i))  //从x开始
        tr[i]+=c;
}
LL sum(LL tr[],int x)
{
    LL res=0;
    for(int i=x;i>0;i-=lowbit(i))
        res+=tr[i];
    return res;
}
LL prefix_sum(int x)
{
    return sum(tr_b,x)*(x+1)-sum(tr_bi,x);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        int b=a[i]-a[i-1];
        add(tr_b,i,b);
        add(tr_bi,i,(LL)b*i);
    }
    while(m--)
    {
        string op;
        int l,r,d;
        cin>>op>>l>>r;
        if(op=="Q")
        {
            cout<<prefix_sum(r)-prefix_sum(l-1)<<endl;
        }
        else
        {
            cin>>d;
            add(tr_b,l,d),add(tr_b,r+1,-d);
            //均只要修改两处
            add(tr_bi,l,l*d),add(tr_bi,r+1,(r+1)*-d);
        }
    }
    return 0;
}


4.2.4 244. 谜一样的牛

image.png


代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n;
int h[N];
int ans[N];
int tr[N];
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i))
        tr[i]+=c;
}
int sum(int x)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))
        res+=tr[i];
    return res;
}
int main()
{
    cin>>n;
    for(int i=2;i<=n;i++)
        cin>>h[i];
    for(int i=1;i<=n;i++)
        tr[i]=lowbit(i);
    for(int i=n;i>0;i--)
    {
        int k=h[i]+1;
        int l=1,r=n;
        while(l<r)
        {
            int mid=(l+r)/2;
            if(sum(mid)>=k) r=mid;
            else l=mid+1;
        }
        ans[i]=r;
        add(r,-1);
    }
    for(int i=1;i<=n;i++)
        cout<<ans[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天前
|
人工智能 算法
程序技术好文:算法与数据结构
程序技术好文:算法与数据结构