AcWing 2154. 梦幻布丁

2024-03-09 16:12
文章标签 acwing 梦幻 布丁 2154

本文主要是介绍AcWing 2154. 梦幻布丁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#include<bits/stdc++.h>using namespace std;//N 表示的是有多少个布丁
//M 表示的是有多少种颜色
const int N=1e5+10,M=1e6+10;//h e ne idx 是链表的组成元素
//表示的是有 M 个颜色,每一个颜色下面连着一个单链表
int h[M],e[N],ne[N],idx;
//n 表示元素个数,m 表示操作次数,ans 表示连续的
//不同颜色的段数
int n,m,ans;
//color 用来存每一个布丁的颜色
//p 用来存映射关系,意思是说,颜色对应的本来是该颜色
//本身,但是由于特殊需要,需要把颜色映射为另一个颜色
//特殊需要是指,我们需要把数目少的颜色的集合合并到
//数目多的颜色的集合中去,但是有可能需要变成的颜色的
//数目是少的集合,此时需要修改映射
//sz 表示的是,颜色的出现次数
int color[N],p[M],sz[M];//单链表的添加操作,表示的是
//把一个数字添加到该颜色往下的一个单链表中
//添加的时候顺便把颜色出现的次数更新
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;sz[a]++;
}//合并两个集合,因为每一次合并都是把小的集合
//合并到大的集合中去,假设小的集合的大小是 x
//合并完成之后,集合的大小至少是 2x
//从而可以把 O(n) 的时间复杂度降到 O(logn)
//需要进行修改操作,需要需要加上引用符号
void merge(int& x,int& y)
{//被操作元素的颜色和需要变成的颜色相等,不需要进行操作if(x==y)return;//被操作颜色的大小更大,需要把两个颜色进行交换//这里交换的是两个映射的数值//比如说原来的 p[x]=1,p[y]=2//sz[x]=10 sz[y]=1//交换之后,p[x]=2,p[y]=1//注意后面的 x,y 表示的都是 p[x] p[y]//交换两个元素,表示把颜色出现次数少的集合//添加到颜色出现次数多的集合后面if(sz[x]>sz[y])swap(x,y);//遍历 x 所在的单链表//~i 等价于 i!=-1//因为 ~(-1)=0for(int i=h[x];~i;i=ne[i]){int j=e[i];//更新答案,假设修改之后的颜色和前一段的颜色相等//答案减小 1 ,假设和后一段颜色相等,答案也减小 1//下面是一种比较简短的写法ans-=(color[j-1]==y)+(color[j+1]==y);}//遍历 x 所在的单链表for(int i=h[x];~i;i=ne[i]){//更新颜色int j=e[i];color[j]=y;//把尾结点指向另一个单链表的头节点if(ne[i]==-1){ne[i]=h[y];//另一个单链表表示的是元素更多的集合//假设不是,前面已经交换过了,所以一定是//元素多的集合的头节点指向当前链表的头节点h[y]=h[x];//把当前链表的头节点初始化为 -1//表示空h[x]=-1;//结束循环break;}}//更新集合的大小sz[y]+=sz[x];//清空小的集合sz[x]=0;
}int main()
{//初始化头节点memset(h,-1,sizeof h);cin>>n>>m;for(int i=1;i<=n;i++){cin>>color[i];//初始化答案if(color[i]!=color[i-1])ans++;//把点添加到单链表中,相当于一条单链表上面挂了//很多单链表add(color[i],i);}//初始化映射,开始是什么颜色就对应什么映射//映射的作用是支持修改for(int i=0;i<M;i++)p[i]=i;while(m--){int op;cin>>op;//输出答案if(op==2)cout<<ans<<endl;else{// x 表示待修改的颜色//y 表示修改之后的颜色int x,y;cin>>x>>y;//p[x] p[y] 表示的是映射的颜色//p 其实是取指针的意思,表示指向的颜色merge(p[x],p[y]);}}return 0;
}

启发式合并

表示的意思是,把元素少的集合合并到元素多的集合中,这样可以使得时间复杂度降低到 log

该题最难的地方在于,假设我们要把一个元素多的颜色修改为一个元素少的颜色,怎么实现上面的要求

解决方案是弄一个指针数组,或者说映射数组,把颜色交换,保证每一次操作都是把出现次数少的颜色修改为出现次数多的颜色

修改头结点和尾结点从而实现合并,等号前面的结点表示从该节点出发,等号右边的结点表示该点是终点,

这篇关于AcWing 2154. 梦幻布丁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/791210

相关文章

【AcWing】851. 求最短路

spfa算法其实是对贝尔曼福特算法做一个优化。 贝尔曼福特算法会遍历所有边来更新,但是每一次迭代的话我不一定每条边都会更新,SPFA是对这个做优化。 如果说dist[b]在当前这次迭代想变小的话,那么一定是dist[a]变小了,只有a变小了,a的后继(b)才会变小。 用宽搜来做优化,用一个队列,队列里边存的就是所有变小了的结点(队列里存的是待更新的点)。 基本思路就是我更新过谁,我再拿

【AcWing】852. spfa判断负环

#include<iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;const int N= 1e5+10;int n,m;int h[N],w[N],e[N],ne[N],idx;int dist[N],cnt[N];//cnt存最短路径的边数bool st[N];v

[数据集][目标检测]轮胎缺陷检测数据集VOC+YOLO格式2154张4类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2154 标注数量(xml文件个数):2154 标注数量(txt文件个数):2154 标注类别数:4 标注类别名称:["debris","ground","side","side_cut"] 每个类别标注的框数: d

AcWing 282. 石子合并

必看的视频讲解↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 【E28【模板】区间DP 石子合并——信息学竞赛算法】 合并过程总开销等于红色数字总和,可以理解为花费的总体力! f数组的含义是f【i】【j】是从第i堆石子开始到第j堆石子的花费体力最小值 如何理解三层for呢? 第一层for是控制区间长度len,第二层for是控制区间起点位置i,第三层for是控制区间

AcWing 897. 最长公共子序列

动态规划就是多见识应用题就完事儿了,也没有什么好说的。 讲解参考: 【E05 线性DP 最长公共子序列】 #include<iostream>#include<algorithm>#define N 1010using namespace std;char a[N],b[N];int n,m;int f[N][N];int main(){cin >> n >> m >> a

AcWing 2. 01背包问题

一定要看的视频讲解:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 【E08【模板】背包DP 01背包——信息学竞赛算法】 i表示放入i个物品,j表示第j个物品,用于访问体积v【j】 #include <iostream>#include <algorithm>using namespace std;const int N = 1010;int n, m;int v[N]

重生奇迹MU敏捷流梦幻骑士

“梦幻骑士”这个职业已经存在于重生奇迹MU中很长时间了,虽然现在已经不算是新职业了,但玩家们对于梦幻骑士的研究和开发一直没有停止过。它作为一个特殊的职业,与传统职业截然不同,拥有着许多独特的玩法。其中,有一种玩法是所有平民玩家的最爱。 敏捷流是目前普遍受欢迎的幻想骑士游戏职业,尤其适合平民玩家选择。它不需要过多的资金投入,只需要将大部分升级点数分配到“敏捷”属性即可。但是,它却能带给玩家出乎意料

poj 2154 Color(polya计数 + 欧拉函数优化)

http://poj.org/problem?id=2154 大致题意:由n个珠子,n种颜色,组成一个项链。要求不同的项链数目,旋转后一样的属于同一种,结果模p。 n个珠子应该有n种旋转置换,每种置换的循环个数为gcd(i,n)。如果直接枚举i,显然不行。但是我们可以缩小枚举的数目。改为枚举每个循环节的长度L,那么相应的循环节数是n/L。所以我们只需求出每个L有多少个i满足gcd(

AcWing-算法提高课(第一章)-下

区间DP 环形石子合并 状态表示:f[i,j](f[i,j]表示,在,由,将第i堆石子到第j堆石子合并成一堆石子的每个合并方式的代价,组成的集合,中,的最小值)状态计算:f[i,j]=min(f[i,k]+f[k+1,j]+s[j]-s[i-1])(s[j]表示第1堆石子到第j堆石子的总重量,s[i-1]表示第1堆石子到第i-1堆石子的总重量,s[j]-s[i-1]表示第i堆石子到第j堆石子的

贪心推公式——AcWing 125. 耍杂技的牛

贪心推公式 定义 贪心算法是一种在每一步选择中都采取在当前状态下最优的选择,希望通过局部的最优选择来得到全局最优解的算法策略。 运用情况 问题具有最优子结构,即一个问题的最优解包含其子问题的最优解。可以通过局部最优决策逐步推导到全局最优。问题的选择策略相对明确且易于计算。 注意事项 贪心算法并不总是能得到全局最优解,可能会陷入局部最优。对于一些复杂问题,需要谨慎验证其正确性。可能需要对