Codeforces Round #555 (Div. 3) E. Minimum Array

题意: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数组中哪些元素是已经使用的就可以了,下面是两种方法。

二分加树状数组维护

#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\n",c[i]);

    }

    return 0;
}
View Code

mutilset删除元素来维护

#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\n",c[i]);
    }

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Carits/p/10786071.html