牛客小白月赛88-DE题解
D-我不是大富翁
题意:![](https://img2024.cnblogs.com/blog/3142690/202403/3142690-20240309111224011-2142253428.png)
做法:一开始是往贪心方面想,但是很明显,贪不了。又因为走的步先后顺序没影响,可以用dp来写。暴力也差不多。
值得注意的点是动力序列可以一边读入一边处理,省了点空间。
如果dp[5005][5005]这样开的话会MLE,实际上在dp的过程中,用到的只是i和i-1两行,其余都是多余的。
所以可以这样定义dp[2][5005]这样可以避免MLE;
还有就是要特判n==1的情况。
//int dp[5005][5005]; //--MLE
int dp[2][5005]; //优化空间!!! wa--5 1 0
//dp[i][j]定义为,到了第i步,可以到达j哪些格子。
//暴力差不多--遍历m步.每步遍历n,看看可以到达哪些格子.看看最后一步是否可以到达1.
void solve(){ //D
int n,m,x;
cin>>n>>m;
if(n==1){ //特判!!
cout<<"YES";
return;
}
dp[0][1]=1;
for(int i=1;i<=m;i++){
cin>>x;
x%=n;
for(int j=1;j<=n;j++){
if(dp[(i+1)%2][j]){
dp[(i+1)%2][j]=0; //重置!!!否则下一步会再次进入
dp[i%2][(j+x)%n]=1;
dp[i%2][(j-x+n)%n]=1;
}
}
}
if(dp[m%2][1]) cout<<"YES";
else cout<<"NO";
}
在写的时候加了个条件判断x==0的情况,但是实际上x==0的情况是相同处理的,不用特别处理。
E-多重映射
题意:![](https://img2024.cnblogs.com/blog/3142690/202403/3142690-20240312234601600-538094275.png)
![](https://img2024.cnblogs.com/blog/3142690/202403/3142690-20240312234637398-577240520.png)
做法有两种。
法一:顺着做,并查集(维护集合的关系,不是值的关系),加一点其他辅助。设置两个unordered_map<int,int>:mp1[集合]=值 ,mp2[值]=集合。
int fa[1000006]; //fa存的是各个集合,不是值!!
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void Union(int x,int y){
int fa1=find(x),fa2=find(y);
fa[fa1]=fa2;
}
//这题顺着做,映射关系有点绕,要想清楚映射关系!!
void solve(){ //E多重映射--①多重映射 or ②正难则反 有T=1e5组样例,ai最大又有1e6。如果每个样例都初始化到1e6--TLE--solve--输入哪个数字初始化哪个数字。
int n,m,arr[100005];
cin>>n>>m;
map<int,int> mp1,mp2; //key!! mp1[集合]=值 : mp2[值]=集合
for(int i=1;i<=n;i++){
cin>>arr[i];
fa[arr[i]]=arr[i];
mp1[arr[i]]=arr[i];
mp2[arr[i]]=arr[i];
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
if(!mp2[x]||x==y) continue; //x不存在于集合
if(!mp2[y]){ //如果y不存在于集合
mp2[y]=mp2[x]; //y存在于x的集合
mp1[mp2[x]]=y; //x的集合对应的值为y
mp2.erase(x); //删除x,x不存在于集合
}
else{
Union(mp2[x],mp2[y]); //集合的Union!!
//x集合已经融入到y集合,所以要先删除x集合对应的值,并且删除x集合。
mp1.erase(mp2[x]);
mp2.erase(x);
}
}
for(int i=1;i<=n;i++) cout<<mp1[find(arr[i])]<<" ";
cout<<endl;
}
法二:巧妙,正难则反。倒着遍历操作。
int fa[1000006];
void solve(){ //E-法二-正难则反
int n,m,arr[100005];
cin>>n>>m;
for(int i=1;i<=n;i++) {
cin>>arr[i];
fa[arr[i]]=arr[i]; //!!!
}
vector<pair<int,int>> vct;
for(int i=1;i<=m;i++){
pair<int,int> x;
cin>>x.first>>x.second;
vct.emplace_back(x);
fa[x.first]=x.first; //!!!所有出现的数字都要初始化为自己
fa[x.second]=x.second;
}
for(int i=m-1;i>=0;i--){
auto [x,y]=vct[i];
fa[x]=fa[y]; //!!!!!!
}
for(int i=1;i<=n;i++){
cout<<fa[arr[i]]<<" ";
}
cout<<endl;
}
妙