【算法提高——第四讲】高级数据结构(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;
}

相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
70 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
1月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
26 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
1月前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
33 4
|
1月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
20 0
数据结构与算法学习十四:常用排序算法总结和对比
|
1月前
|
存储 缓存 分布式计算
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
这篇文章是关于数据结构与算法的学习指南,涵盖了数据结构的分类、数据结构与算法的关系、实际编程中遇到的问题以及几个经典的算法面试题。
31 0
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
|
1月前
|
机器学习/深度学习 存储 算法
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
|
2月前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。
|
1月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
|
1月前
|
算法 Java 索引
数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
21 0
|
1月前
|
存储 算法 Java
数据结构和算法--分段树
数据结构和算法--分段树
16 0