CF873E Awards For Contestants(st表)

如果枚举三维会超时,但是暴力做法却很有道理,根据数据范围,容易看出这是个n^2的题目,并且第三个点是一个区间中的答案

因此考虑用st表查询区间最值优化

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
    int a;
    int id;
}s[N];
int ans[N];
int st[N][30];
bool cmp(node a,node b){
    return a.a>b.a;
}
int calc(int i){
    return s[i].a-s[i+1].a;
}
int Query(int L,int R){
    if (L>R)
        return -1;
    int d=log(R-L+1)/log(2.0);
    int a=st[L+(1<<d)-1][d],b=st[R][d];
    return calc(a)>calc(b)?a:b;
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>s[i].a;
        s[i].id=i;
    }
    sort(s+1,s+1+n,cmp);
    for (int i=1;i<=n;i++){
        st[i][0]=i;
        for(int j=1;j<=12;j++){
            st[i][j]=st[i][j-1];
            if (i-(1<<(j-1))>0&&calc(st[i-(1<<(j-1))][j-1])>calc(st[i][j]))
                st[i][j]=st[i-(1<<(j-1))][j-1];
        }
    }
    int d1=-1,d2=-1,d3=-1;
    for(int i=1;i<=n;i++)
        for(int j=1;i+j<=n;j++){
            if(i>2*j||j>2*i)
                continue;
            int dd1=i,dd2=i+j,dd3=Query(dd2+max((i+1)/2,(j+1)/2),min(dd2+min(i*2,j*2),n));
            int k=dd3-dd2;
            if(dd3==-1||k<1)
                continue;
            if(d1==-1||calc(dd1)>calc(d1)||(calc(dd1)==calc(d1)&&(calc(dd2)>calc(d2)||(calc(dd2)==calc(d2)&&calc(dd3)>calc(d3)))))
                d1=dd1,d2=dd2,d3=dd3;
        }
    for(i=1;i<=d1;i++){
        ans[s[i].id]=1;
    }
    for(i=d1+1;i<=d2;i++){
        ans[s[i].id]=2;
    }
    for(i=d2+1;i<=d3;i++)
        ans[s[i].id]=3;
    for(i=d3+1;i<=n;i++)
        ans[s[i].id]=-1;
    for(i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}
View Code

 

posted @ 2020-12-03 20:23  朝暮不思  阅读(140)  评论(0编辑  收藏  举报