如果你觉得并查集难以理解的话请看此篇
题意:求字典序最小
思路:
比较字典序最小,类似于字符串的比较:只要前面保证最小即可,如:1000大于0111
首先最简单,考虑暴力枚举每个b数组,使得取模后最小,时间复杂度为n^2,(注意:使用后的b数组应该删除)
暴力肯定会wa,所以考虑优化
因为是查找b数组中的值,且可以任意排序,考虑二分优化
查找b数组大于等于(n-a[i])的第一个值
1.如果b数组存在(n-a[i]),优先使用,因为该值取模后为零,字典序肯定最小
2.如果1不满足,则查找第一个大于(n-a[i])的值,因为b数组的值最大为n-1,所以取模后一定小于a[i]
特判
3.如果不存在大于等于(n-a[i])的值,那么使用最小值,这样该位置的值最小
注意:用过的值要删掉(或者过滤,实现方法很多)
如:
1.如果该位置为4,n=7,b数组为 1,4。则b数组选4,最小
2.如果该位置为4,n=7,b数组为 1,2.则b数组选1,最小
ok,到此,思路结束,下面是我的做法
1.利用map存储b数组,map会自己排序
2.利用lower_bound(查找第一个大于等于x的地址)
3.删除用erase
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N];
map<int,int> ma;
int main(){
// ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) {
cin>>b[i];
ma[b[i]]++;
}
for(int i=1;i<=n;i++){
auto it=ma.lower_bound(n-a[i]);
if(it!=ma.end()){//如果能找到,使用该值
cout<<(a[i]+(*it).first)%n<<' ';
if(--(it->second)==0) ma.erase(it);
}
else{//如果找不到,则使用最小值
auto id=ma.begin();
cout<<(a[i]+id->first)%n<<' ';
if(--(id->second)==0) ma.erase(id);
}
}
return 0;
}