CF1687D Cute number 题解

题目链接

点击打开链接

题目解法

一个数 \(c\) 是可爱(下文称为合法)的,当且仅当 \(c\in [x^2,x(x+1)]\)
\(a_i\) 属于 \([x_i,x_i(x_i+1)]\)
一个显然的范围是 \(x_1\le 2\times 10^6\)

考虑枚举 \(x_1\)
现在说明一个结论:\(x_1\) 固定时,\(x_i\) 也固定了
说明:不难发现,合法的不合法的范围是交替的,且长度为 $(l+1),l,(l+2),l+1,...,(t+1),t,... $,其中打括号的是合法的长度,一共只有 \(x_1+1\) 个范围,而跨块起码需要 \(x_1+2\),所以显然 \(x_i\) 固定
这样可以做到 \(O(nV)\) 的复杂度

下面是我没想到的
\(a_i\) 的范围较小,考虑如何优化?
如果 \(a_i-a_{i-1}\ge x_1\),那么 \(i-1\)\(i\) 一定在同一块了
我们把这些一定在同一块的一起做
时间复杂度就可以优化到 \(O(n+V)\)

我写的比较丑,多写了一个并查集,所以复杂度为 \(O(n\alpha(n)+V)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=2000100;
int n,a[N],ne[N],fa[N];
vector<int> gap[N];
int get_father(int x){ if(x==fa[x]) return x;return fa[x]=get_father(fa[x]);}
int main(){
    n=read();
    F(i,1,n) a[i]=read();
    F(i,1,n-1) gap[a[i+1]-a[i]].pb(i);
    F(i,1,n) ne[i]=i+1,fa[i]=i;
    for(int p:gap[0]) ne[get_father(p)]=ne[p+1],fa[p+1]=fa[p];
    F(x,1,2000000){
        for(int p:gap[x]) ne[get_father(p)]=ne[p+1],fa[p+1]=fa[p];
        LL lo=max(0ll,1ll*x*x-a[1]),hi=1ll*x*(x+1)-a[1];
        for(int p=1;p<=n;p=ne[p]){
            int q=ne[p]-1;
            int xx=sqrt(lo+a[p]);
            if(1ll*xx*(xx+1)<lo+a[p]) xx++;
            chkmax(lo,1ll*xx*xx-a[p]),chkmin(hi,1ll*xx*(xx+1)-a[q]);
            if(lo>hi) break;
        }
        if(lo>hi) continue;
        printf("%lld\n",lo);exit(0);
    }
    return 0;
}

posted @ 2024-02-02 13:44  Farmer_D  阅读(13)  评论(0)    收藏  举报