ARC136E Non-coprime DAG [关键性质题]

Description

构造一个有向图,\(i\to j\) 的边存在,当且仅当 \(i<j\)\(\text{gcd}(i,j)>1\),求一个反链 \(S\),使得 \(\sum\limits_{i\in S}A_i\) 最大。
反链指的是一个点集,任意两点都不能到达。

Solution

考虑 \(i\) 可以到达 \(j\) 需要满足什么条件,下面我们钦定 \(i<j\),设 \(f(i)\) 表示 \(i\) 的最小质因子,

  • \(1\) 不能到达任何点,也不能被任何点到达。
  • \(i\)\(j\) 都是偶数时,显然存在 \(i\to j\)
  • \(i\) 是奇数,\(j\) 是偶数时,\(i\to j\) 存在当且仅当 \(i+f(i)\le j\)
  • \(i\) 是偶数,\(j\) 是奇数时,\(i\to j\) 存在当且仅当 \(i\le j-f(j)\)
  • \(i\)\(j\) 都是奇数时,\(i\to j\) 存在当且仅当 \(i+f(i)\le j-f(j)\)

如何理解以上式子呢,
可以将 \(i+f(i)\) 看作 \(i\) 能到达的 编号最小的点,将 \(j-f(j)\) 看作 能到达 \(j\) 编号最大的点,
\(i\)\(j\) 都是奇数,那加上或减去 \(f\) 就应当是偶数,我们知道偶数是可以到达的,但仅限于小的编号到大的编号,所以 \(i\to j\) 存在当且仅当 \(i+f(i)\le j-f(j)\)

于是我们可以把 \(i\) 的影响范围看作一个区间 \([i-f(i)+1,f+f(i)-1]\),这个区间内所有点都是和 \(i\) 没边的,偶数 \(i\) 的影响区间是 \([i,i]\)
那么我们对于每个点,将它的影响区间都加上它的权值 \(a_i\)。我们知道反链之间是没边的,所以反链中所有点的影响区间都会有交集,因此累加权值的时候就刚好计算了答案,取最大的一个即可。
对于区间加,可以用差分维护,\(dif[i-f(i)+1]+a[i]\to dif[i-f(i)+1]\)\(dif[i+f(i)]-a[i]\to dif[i+f(i)]\)

Code

const int N = 1e6 + 5;

int n;
ll a[N], dif[N];
int f[N], prime[N], cnt;

void Solve(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }

    for(int i = 2; i <= n; i++){
        if(!f[i]) f[i] = prime[++cnt] = i;
        for(int j = 1; j <= cnt && prime[j] <= n / i; j++){
            f[prime[j] * i] = prime[j];
            if(i % prime[j] == 0) break;
        }
    }

    for(int i = 2; i <= n; i++){
        if(i & 1) dif[i - f[i] + 1] += a[i], dif[i + f[i]] -= a[i];
        else dif[i] += a[i], dif[i + 1] -= a[i];
    }
    dif[1] += a[1], dif[n + 1] -= a[1];

    ll ans = 0;
    for(int i = 1; i <= n; i++){
        dif[i] += dif[i - 1];
        ans = max(ans, dif[i]);
    }
    cout << ans << endl;
}
posted @ 2024-10-10 18:54  chenwenmo  阅读(1)  评论(0编辑  收藏  举报