第五章:优先队列、并查集(7.22、7.23)

堆:

模板:

NC16663 合并果子

还是打一下板子吧

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
priority_queue<int, vector<int>, greater<int> > q;
int a[10005];
int main()
{
    int n;scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]),q.push(a[i]);
    int ans=0;
    while(q.size()>=2)
    {
        int x=0;
        x+=q.top();q.pop();
        x+=q.top();q.pop();
        ans+=x;
        q.push(x);
    }
    printf("%d\n",ans);
}
合并果子

NC214362 第k小

维护size为k的大顶堆

对顶堆:

NC50940 Running Median

经典动态维护序列中位数

大根堆维护较小的一半元素,小根堆维护较大的一半元素

奇数个时,元素更多的那一堆的堆顶为中位数

贪心:

NC20185 [JSOI2010]缓存交换

对于当前的i,如果要清理一个空间,就清理后面最晚出现的那个(贪心)

用nextt[i]和堆维护

可以后悔的贪心:

NC50439 tokitsukaze and Soldier

从大到小枚举s[i]的值。在所有>=s[i]的士兵中选v最大的s[i]个,用优先队列维护。因为s[i]是减小的。所以删除的士兵一定在后面用不到。

map/set:

map资料参考

基本运用:

NC235267 星球大战

虽然是1e9的x和y,但用map就可以解决

注意map怎么写

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    map<int,list<int> >mp;
    map<int,list<int> >mp1;
    for(int i=1;i<=n;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        mp1[x].push_back(y);
        mp[y].push_back(x);
    }
    for(int i=1;i<=m;i++)
    {
        int c,d;scanf("%d%d",&c,&d);
        int cnt=0;
        if(c==1)
        {
            printf("%d\n",mp[d].size());
            for(auto i:mp[d])mp1[i].remove(d);
            mp[d].clear();  
        }
        else
        {
            printf("%d\n",mp1[d].size());
            for(auto i:mp1[d])mp[i].remove(d);
            mp1[d].clear();  
        }
    }
    return 0;
}

并查集:

维护附加信息:

NC235622 叠积木

带权并查集,下面的为父亲

#include<bits/stdc++.h>
using namespace std;
int fa[30005],siz[30005],d[30005];
int get(int x)
{
    if(x==fa[x])return x;
    int f=get(fa[x]);
    d[x]+=d[fa[x]];
    fa[x]=f;
    return fa[x];
}
int main()
{
    int T;scanf("%d",&T);
    for(int i=1;i<=30000;++i)fa[i]=i,siz[i]=1,d[i]=0;
    
    while(T--)
    {
        getchar();
        char c;scanf("%c",&c);
        if(c=='M')
        {
            int x,y;scanf("%d%d",&x,&y);
            int f1=get(x),f2=get(y);
            if(f1==f2)continue;
            fa[f1]=f2;
            d[f1]=siz[f2];
            siz[f2]+=siz[f1];
        }
        else
        {
            int x;scanf("%d",&x);
            get(x);
            printf("%d\n",d[x]);
        }
    }
}
 
叠积木
posted @ 2022-07-25 21:05  yyys  阅读(23)  评论(0编辑  收藏  举报