CF1223G Wooden Raft 题解
CF1223G Wooden Raft
解析
观察一下所求的答案是一个乘积的形式,而
首先枚举
只能枚举
- 从一根木棒截取:
对于多余的
假设完全分割可以得到的长度为
- 从两根木棒截取
同样可以采用和 1 相同的贪心思路,对于分别取出
时间复杂度方面,令
#include<iostream>
#include<cstdio>
#include<algorithm>
using std::cin;using std::cout;
constexpr int N=1000006;
int n,a,c[N],pre[N],m,cnt;
long long ans;
inline void max(int x,int y){ans=std::max(ans,1ll*(x>1)*x*y);}
signed main(){
freopen("poly.in","r",stdin);
freopen("poly.out","w",stdout);
std::ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
cin>>n;for(int i=1;i<=n;++i){cin>>a;++c[a];m=std::max(m,a);}pre[0]=-1;//为了方便计算及查找区间内是否存在木棒,我们对木棒的长度开桶。
for(int i=1;i<=2*m;++i){
if(c[i]) pre[i]=i;
else pre[i]=pre[i-1];
c[i]+=c[i-1];
}
for(int i=2;i<=m;++i){
cnt=0;
for(int j=i;j<=m;j+=i) cnt+=(c[j+i-1]-c[j-1])*(j/i);
int mx1=0,mx2=0;
for(int j=m/i;j>=0;--j){
int L=j*i,R=L+i-1;
if(pre[R]>=L&&pre[R]%i>mx1%i) mx1=pre[R];
max(std::min(cnt-j,j*i+mx1%i>>1),i);
}
mx1=0;
for(int j=m/i;j>=0;--j){
int L=j*i,R=L+i-1;
if(mx1&&mx2){
max(std::min(cnt-2*j-1,j*i+mx1%i),i);
max(std::min(cnt-2*j,j*i+mx2%i),i);
}
if(mx1&&pre[R]>=L&&pre[R]%i>mx2%i){//新取一根
if(pre[R]%i>=mx1%i){
max(std::min(cnt-2*j-1,pre[R]),i);
max(std::min(cnt-2*j,j*i+mx1%i),i);
}else max(std::min(cnt-2*j,pre[R]),i);
//有些时候另外一种取法可以省略,具体原因呢可以自己分析
}
R=pre[R];
if(R>=L){//多取多好
if(R%i>=mx1%i){mx2=mx1;mx1=R;}
else if(R%i>mx2%i) mx2=R;
R=c[R]-c[R-1]>1?R:pre[R-1];
if(R>=L&&R%i>mx2%i) mx2=R;
}
if(mx1&&mx2) max(std::min(cnt-2*j,j*i+mx2%i),i);
}
}
cout<<ans;
return 0;
}//第五十四回 史太君破陈腐旧套 王熙凤效戏彩斑衣