[USACO22JAN] Tests for Haybales G

Farmer John 的奶牛们决定为 Farmer Nhoj 农场的奶牛们举办一场编程竞赛。为了使问题尽可能有趣,他们花费了大量时间来构造具有挑战性的测试用例。特别是对于一个问题,「Haybales」,奶牛们需要你的帮助来设计具有挑战性的测试用例。这有关解决以下这个有些奇妙的问题:

有一个有序整数数组 x 1 ≤ x 2 ≤ ⋯ ≤ x N x_1 \leq x_2 \leq \dotsb \leq x_N x1x2xN 1 ≤ N ≤ 1 0 5 1 \leq N \leq 10^5 1N105),和一个整数 K K K。你不知道这个数组以及 K K K,但你知道对于每个索引 i i i 使得 x j i ≤ x i + K x_{j_i} \leq x_i + K xjixi+K 的最大索引 j i j_i ji。保证有 i ≤ j i i\le j_i iji 以及 j 1 ≤ j 2 ≤ ⋯ ≤ j N ≤ N j_1\le j_2\le \cdots \le j_N\le N j1j2jNN

给定这些信息,Farmer John 的奶牛需要构造任意一个数组以及整数 K K K 与该信息一致。构造需要满足对于所有 i i i 0 ≤ x i ≤ 1 0 18 0 \leq x_i \leq 10^{18} 0xi1018,并且 1 ≤ K ≤ 1 0 18 1 \leq K \leq 10^{18} 1K1018

可以证明这一定是可行的。请帮助 Farmer John 的奶牛们解决这一问题!


先将 j i j_i ji 都加上 1 1 1,这样 j i j_i ji 就表示最大的满足 x j i > x i + K x_{j_i}>x_i+K xji>xi+K 的下标。

i i i j i j_i ji 之间连边,最终会得到一棵树,以 n + 1 n+1 n+1 为根。

由于 x j i x_{j_i} xji x i x_{i} xi 的差大约为 K K K,于是(通过人类智慧)猜测 x i x_i xi 形如 x ⋅ K + y ( 0 ≤ y < K ) x\cdot K+y(0\le yxK+y(0y<K) x x x 显然与深度有关,下面考虑求 y y y

根据 x j i > x i + K x_{j_i}>x_i+K xji>xi+K,可得 y u y_u yu 大于其所有儿子的 y y y 值,意味着 y u ≥ y_u\ge yu 其子树所有的 y y y 值。(通过人类智慧)发现树的 dfs 序完美不符合条件,于是令 y u = K − d f n u y_u=K-dfn_u yu=Kdfnu,这样就行了。

注意 x i x_i xi 为自然数, K K K 只需 ≥ n + 1 \ge n+1 n+1 即可。

时间复杂度 O ( n ) O(n) O(n)

#include
using namespace std;
const int N=1e5+10;
int n,k,dep[N],ans[N],num;
int head[N],nxt[N<<1],to[N<<1],cnt;
void add(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
void dfs(int u)
{
    ans[u]=--k;
    for(int i=head[u];i;i=nxt[i]) dep[to[i]]=dep[u]+1,dfs(to[i]);
}
int main()
{
    cin.tie(0)->sync_with_stdio(0);
    cin>>n;
    cout<<(k=num=n+2)<<"\n";
    for(int i=1,x;i<=n;i++){
        cin>>x;
        add(x+1,i);
    }
    dfs(n+1);
    for(int i=1;i<=n;i++) cout<<1ll*num*(dep[1]-dep[i])+ans[i]<<"\n";
}

你可能感兴趣的:(图论)