1. 程式人生 > 實用技巧 >CF873E Awards For Contestants(st表)

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