ARC163E Non-coprime DAG

给定一张\(n\)个点的图\(G\)

\(i < j,gcd(i,j) > 1\),有一条\(i\to j\)的边。

给定点权\(A_i\)

求选出带权最长反链。

做法:

根据\(diworth\)定理,带权最长反链等于带权可重最小路径覆盖。
于是我们使用二分图模型,费用流即可。
于是
成功输了。
完全输了。

考虑只会选择一个偶数。

其提醒我们思考如何处理选出的数全是奇数的情况。

考虑当\(x < y\)如何可以同时被选。

\(L_x\)\(x\)的最小质因数。

给出结论为\(x + L_x > y - L_y\)

考虑若\(x+L_x \leq y+L_y\),考虑如下路径\(x \to x + L_x \to y - L_y \to y\),第三步是因为二者都是偶数。

\(x + L_x > y - L_y\),则不可能走超过\(2\)步,则考虑是否存在\(x + p = y\)为两者共同约数,由于其全为奇数则不可能。

那么我们只要对所有奇数的区间\([x - L_x,x + L_x]\),选一个点让覆盖其的区间的权值和最大即可。

考虑偶数带来的影响,发现前缀证明不变仅影响到了\(x + p = y\).考虑\(x\)为偶数,考虑若\(z = y - x\),若其不等于\(L_y\),则\(z - L_y >= 2\)不满足第二个条件的先决条件,所以只需考虑\(x + L_y = y\)

那么我们考虑将原本的奇数区间写作\([x - L_x + 1,x + L_x - 1]\),偶数写作\([x,x]\)即可差分实现其。

ARC163E Non-coprime DAG
#include<bits/stdc++.h>
#define ll long long 
#define N 1000005

int n;
ll a[N];
ll s[N * 2];
int L[N];

inline void sieve(){
	for(int i = 2;i < N;++i){
		if(!L[i]){
			for(int j = 1;j * i < N;++j)
			if(!L[i * j])L[i * j] = i;
		}
	}
}

ll mx;

int main(){
	sieve();
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)
	scanf("%lld",&a[i]);
	for(int i = 1;i <= n;++i)
	if(i & 1){
		s[i - L[i] + 1] += a[i];
		s[i + L[i]] -= a[i];
	}else{
		s[i] += a[i];
		s[i + 1] -= a[i];
	}
	for(int i = 2;i <= n * 2;++i)
	s[i] = s[i] + s[i - 1],mx = std::max(mx,s[i]);
	std::cout<<mx + a[1]<<"\n";
}
posted @ 2022-02-28 20:05  fhq_treap  阅读(123)  评论(0编辑  收藏  举报