题意:b数组可以自由排序,c[i]=(a[i]+b[i])%n.
题目中要求c数组的字典序是最小的。那么我们需要尽量满足前面的c[i],才能使字典序最小。
我们知道a[i]和b[i]都是[0,n-1]的范围内。那么我们容易得到
如果a[i]+b[i]>=n,(a[i]+b[i])%n<a[i]且(a[i]+b[i])%n<b[i]。得出这样的结论之后,我们就可以进行模拟了。
如果当前a[i]能找到一个b[i]使得a[i]+b[i]>=n,那么我们就找符合条件最小的元素,否则的话a[i]加上最小的b[i]才满足的字典序最小。
我们需要做的就是维护b数组中哪些元素是已经使用的就可以了,下面是两种方法。
二分加树状数组维护
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<vector> #include<stack> #include<algorithm> #include<cstdio> #include<map> #include<string> #include<cstring> using namespace std; map<int,int>p; int a[200005]; int b[200005]; int c[200005]; bool vis[200005]; int sum[200005]; int n; inline int lowbit(int x) { return x&(-x); } void update(int x,int num) { while(x<=n) { sum[x]+=num; x+=lowbit(x); } } int getsum(int x) { int s=0; while(x>0) { s+=sum[x]; x-=lowbit(x); } return s; } int main() { int t,i,maxi,l,r,t1,t2,l1,r1,m1,m2,m; while(cin>>n) { memset(sum,0,sizeof(sum)); for(i=1; i<=n; i++) scanf("%d",&a[i]),update(i,1); for(i=1; i<=n; i++) scanf("%d",&b[i]); sort(b+1,b+n+1); memset(vis,false,sizeof(vis)); m1=1; for(i=1;i<=n;i++) { t=lower_bound(b+1,b+n+1,n-a[i])-(b); while(m1<=n&&vis[m1]) m1++; l=t-1; r=n+1; if(t!=n+1) while(l+1<r) { m=(l+r)>>1; if(getsum(m)-getsum(t-1)>0) r=m; else l=m; } t=r; if(t>n) { c[i]=(a[i]+b[m1])%n; vis[m1]=true; update(m1,-1); while(vis[m1]&&m1<=n) m1++; } else { c[i]=(a[i]+b[t])%n; update(t,-1); vis[t]=true; } } for(i=1;i<=n-1;i++) printf("%d ",c[i]); printf("%d ",c[i]); } return 0; }
mutilset删除元素来维护
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<vector> #include<stack> #include<algorithm> #include<cstdio> #include<map> #include<string> #include<cstring> #include<set> using namespace std; map<int,int>p; int a[200005]; int b[200005]; int c[200005]; bool vis[200005]; int sum[200005]; int n; int main() { int t,i,maxi,l,r,t1,t2,l1,r1,m1,m2,m; while(cin>>n) { multiset<int>mm; for(i=1; i<=n; i++) scanf("%d",&a[i]); for(i=1; i<=n; i++) scanf("%d",&b[i]),mm.insert(b[i]); memset(vis,false,sizeof(vis)); m1=1; for(i=1;i<=n;i++) { multiset<int>::iterator it=mm.lower_bound(n-a[i]); if(it!=mm.end()) { c[i]=((*it)+a[i])%n; mm.erase(it); } else { it=mm.begin(); c[i]=(*it)+a[i]; mm.erase(it); } } for(i=1;i<=n-1;i++) printf("%d ",c[i]); printf("%d ",c[i]); } return 0; }