地址:https://codeforces.com/contest/1157/problem/E
题意:给了两个数组a和b,范围都是0~(n - 1),对每个a数组的值,到b数组找一值进行(a[i] + b[j]) % n,形成数组c,最后要数组c最小,输出c数组
解法:一看就是贪心,a数组顺序遍历,到b数组找一个未用过的数,与当前数计算后得到的值最小,因为a[i]与n - a[i]形成的值是0,二分找到第一个大于等于n - a[i]的数,如果没找到,就找最小的数;
原先一直想着n - a[i] ~ (n - 1) ~ 0 ~ (n - a[i] - 1),顺序找到第一个满足的数,这样必超时,不知道怎么二分,其实就是可以直接先找n - a[i] ~ (n - 1),二分找到第一个大于等于n - a[i]的数,如果没找到,就到0 ~ (n - a[i] - 1)找最小的数。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int N = 2 * 1e5 + 5;
int a[N];
int b[N];
int c[N];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;++i){
scanf("%d",&a[i]);
}
multiset<int>ss;
for(int i = 1;i <= n;++i){
scanf("%d",&b[i]);
ss.insert(b[i]);
}
for(int i = 1;i <= n;++i){
int tmp = n - a[i];
multiset<int>::iterator pos = ss.lower_bound(tmp);
if(pos == ss.end()){//没找到第一个大于等于tmp的数
c[i] = (a[i] + *ss.begin()) % n;
ss.erase(ss.begin());
}else{//找到第一个大于等于tmp的数
c[i] = (a[i] + *pos) % n;
ss.erase(pos);
}
}
for(int i = 1;i <= n;++i){
if(i == n){
printf("%d\n",c[i]);
}else{
printf("%d ",c[i]);
}
}
return 0;
}