[codeforces873E]Awards For Contestants

来源:互联网 发布:淘宝极品买家秀 编辑:程序博客网 时间:2024/05/15 14:47

题目大意

给定n个正整数,要把它们放进三个组(分别为1号组,2号,3号),也可以不放。每组至少要有一个数。同时对于对于1,2,3号组,两两直接必须满足cnt[p]≤2*cnt[q],其中cnt[x]表示x号组有多少个数。对于两个数x,y,如果x < y,那么y不能放在编号比x大的组。
定义c[x]表示x号组的最大数,d[x]是x号组的最小数。特殊地,c[-1]表示没有放的数的最大值,d[-1]同理。现在求一个合法分配方案,最大化{d[1]-c[2],d[2]-c[3],d[3]-c[-1]}的字典序。

n≤3000,正整数大小不超过5000

分析

首先给n个数降序排序,容易发现这等价于把排序后的数组分成4段,其中前三段是要满足cnt两两不超过彼此两倍的条件。
然后可以枚举第1组的边界和第2组的边界,然后合法的第三组的边界就是一个区间,查询区间内的最大值即可。这里我写了个rmq。所以时间复杂度是O(n2)

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=3005,Log=12;typedef long long LL;int n,a[N],diff[N],m1,m2,m3,Ans[N],L[N],rmq[Log][N];struct Data{    int x,ID;}A[N];bool operator < (const Data &a,const Data &b){    return a.x<b.x;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++)    {        scanf("%d",&a[i]); A[i].ID=i; A[i].x=a[i];    }    sort(A+1,A+n+1);    for (int i=0;i<n;i++) rmq[0][i]=i,diff[i]=A[i+1].x-A[i].x;    m1=-1;    for (int i=1,j=0;i<=n;i<<=1,j++) L[i]=j;    for (int i=3;i<=n;i++) if (!L[i]) L[i]=L[i-1];    for (int j=1;j<Log;j++)        for (int i=0;i<=n-(1<<j);i++)            rmq[j][i]=(diff[rmq[j-1][i]]>=diff[rmq[j-1][i+(1<<j-1)]])?rmq[j-1][i]:rmq[j-1][i+(1<<j-1)];    for (int i=n+1>>1;i<n;i++) if (m1==-1 || diff[i]>=diff[m1])    {        int j,k,l,r,p=n-i,q;        for (int j=1;j<n;j++)        {            q=i-j;            if (2*p<q || 2*q<p || j*2<q || j*2<p) continue;            if (p>q) l=p+1>>1,r=q<<1;else l=q+1>>1,r=p<<1;            if (l<=r)            {                r=max(0,j-r); l=max(0,j-l); swap(l,r);                k=L[r-l+1];                k=(diff[rmq[k][l]]>=diff[rmq[k][r-(1<<k)+1]])?rmq[k][l]:rmq[k][r-(1<<k)+1];                if (m1==-1 || (diff[m1]<diff[i] || diff[m1]==diff[i] && (diff[m2]<diff[j] || diff[m2]==diff[j] && diff[m3]<diff[k])))                {                    m1=i; m2=j; m3=k;                }            }        }    }    for (int i=n;i>m1;i--) Ans[A[i].ID]=1;    for (int i=m1;i>m2;i--) Ans[A[i].ID]=2;    for (int i=m2;i>m3;i--) Ans[A[i].ID]=3;    for (int i=m3;i;i--) Ans[A[i].ID]=-1;    for (int i=1;i<n;i++) printf("%d ",Ans[i]); printf("%d\n",Ans[n]);    return 0;}
原创粉丝点击