专栏文章

ARC190E

AT_arc190_e题解参与者 2已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@miqikjoq
此快照首次捕获于
2025/12/04 05:23
3 个月前
此快照最后确认于
2025/12/04 05:23
3 个月前
查看原文
一个全新的领域!
众所周知,二分图最大匹配为:VLmaxSVL(SN(S))|V_{L}|-\max_{S\in V_L}(|S|-|N(S)|),霍尔定理推论。
霍尔定理相关题目已经出了很多很多,诞生了许多好题。
聪明的出题人一定不会满足于此,走向全新的领域:一般图!
一般图最大匹配为:12(VmaxSV(O(VS)S))\frac{1}{2} (|V|-\max_{S\in V}(O(V-S)-|S|)),其中 O(VS)O(V-S) 表示把图扣去集合 SS 中的点之后大小为奇数的连通块个数,在学术上被称作:Tutte-Berge Formula。证明部分略去,有兴趣自行了解(我还不太会,待学习)
言归正传,那么本题先可以简单得建立出一般图最大匹配模型:两个距离小于等于 22 的点之间连一条边,保留区间中的所有点,跑最大匹配。
那么我们现在只用考虑求 maxSVO(VS)S\max_{S\in V}O(V-S)-|S|
注意到这里是带权的最大匹配(每个点包含了 aia_i 个点),可以发现一个点要么全部选入 SS,要么全没有选入 SS,具体而言,假设最终 SS 中选了 0<x<ai0< x <a_i 个点,那么调整成选 x1x-1 个点一定不劣。
不妨设 di=1/0d_i=1/0 表示下标 ii 的所有点选/没选入 SS,考虑设计 dpdp 转移。
不妨设区间长度为 mm,以及 d0=dm+1=1d_0=d_{m+1}=1,方便处理边界。
首先答案为奇 00 连通块个数减去所有 11 的带权和,当然会有细节需要你考虑。
当一个 00 形成一个独立连通块时,贡献为 aia_i 并非 11(每个点都是孤立的)
000100000100 出现时即中间只有一个 11 间断两边的 00 其实是一个连通块,这种情况是烦人的,但是你直接钦定全局不能出现这种情况即可(有支配性:不如把 11 改为 00,可调整证明)
ai=0a_i=0 的时候是不能选 di=1d_i=1 的,但是 di=0d_i=0 不劣于 di=1d_i=1 的,所以不需要特殊处理。
然后就可以 dpdp 转移了,设 fi,0/1/2/3/4f_{i,0/1/2/3/4} 表示当前考虑了 1i1\sim iii 号点当前状态为:单独的一个 11,在多个 11 的连通块内,单独的一个 00,在多个 00 的联通块内且当前连通块大小为偶数/奇数。
列出矩阵 (max+)做转移即可,细节看代码。
复杂度 O((n+qlog)K3)O((n+q\log)K^3)KK 为矩阵大小,本题还能支持单点修改。
一道很牛牛的题,感觉这个结论扩展性极强,期待下一次遇见。
CPP
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll N=2e5+3,K=5,INF=1e18;
ll n,m,a[N],sa[N];
void Max(ll &x,ll y){if(x<y)x=y;}
struct Mat
{
	array<ll,K>f[K];
	auto& operator[](int x){return f[x];}
	void Clear(){memset(f,0xcf,sizeof(f));}
	friend Mat operator *(Mat A,Mat B)
	{
		Mat C;C.Clear();
		for(int i=0;i<K;i++)for(int k=0;k<K;k++)for(int j=0;j<K;j++)
			Max(C[i][j],A[i][k]+B[k][j]);
		return C;
	}
}I;
void Init(){for(int i=0;i<K;i++)for(int j=0;j<K;j++)I[i][j]=i==j?0:-INF;}
Mat Get(ll v)
{
	Mat A;
	if(v%2==0)
	{
		A[0]={-INF,-v,-INF,-INF,-INF};
		A[1]={-INF,-v,v,0,-INF};
		A[2]={-v,-INF,-INF,-INF,-INF};
		A[3]={-v,-INF,-INF,0,-INF};
		A[4]={-v,-INF,-INF,-INF,0};
	}
	else
	{
		A[0]={-INF,-v,-INF,-INF,-INF};
		A[1]={-INF,-v,v,-INF,1};
		A[2]={-v,-INF,-INF,-INF,-INF};
		A[3]={-v,-INF,-INF,-INF,1};
		A[4]={-v,-INF,-INF,-1,-INF};
	}
	return A;
}
struct SGT
{
	int DT;Mat tr[1<<19|3];
	void Up(int p){tr[p]=tr[p<<1]*tr[p<<1|1];}
	void Build()
	{
		DT=1<<(__lg(n)+1);
		for(int i=1;i<=n;i++)tr[i+DT]=Get(a[i]);
		for(int i=DT-1;i;i--)Up(i);
	}
	Mat Ask(int l,int r)
	{
		Mat sl=I,sr=I;
		for(l+=DT-1,r+=DT+1;l+1!=r;l>>=1,r>>=1)
		{
			if(~l&1)sl=sl*tr[l+1];
			if(r&1)sr=tr[r-1]*sr;
		}
		return sl*sr;
	}
}T;
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m;Init(); 
	for(int i=1;i<=n;i++)cin>>a[i],sa[i]=sa[i-1]+a[i];
	T.Build();
	for(int i=1,l,r;i<=m;i++)
	{
		cin>>l>>r;Mat t=T.Ask(l,r);
		ll ans=*max_element(t[1].begin(),t[1].end());
		cout<<(sa[r]-sa[l-1]-ans)/2<<"\n";
	}
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...