1 条题解

  • 0
    @ 2026-5-19 18:01:59

    显然一只蚂蚁与一块方糖匹配,是类似图匹配的结构。那么考虑考虑朝距离 L\le L 的所有方糖连一条边,这个二分图的最大匹配就是答案。

    分别记 ai,bia_i,b_i 为位置 ii 的蚂蚁数和方糖数。

    运用 Hall 定理,我们知道二分图最大匹配是 $\sum a_i-\max\limits_{S}\{0,\sum_{i \in S}a_i-\sum_{i \in N(S)}b_i\}$。

    考虑将 SS 表示为 kk 个不交区间的并 [l1,r1][l2,r2][lk,rk][l_1,r_1]\cup [l_2,r_2]\cup\cdots\cup[l_k,r_k]

    则 $N(S)=\big[l_1-L,r_1+L\big]\cup \big[l_2-L,r_2+L\big]\cup\cdots\cup\big[l_k-L,r_k+L\big]$。

    这些区间也最好不交,这要求了 li+1ri>2Ll_{i+1}-r_i >2L

    如果出现了 li+1ri2Ll_{i+1}-r_i \le 2L,我们可以将区间 [li,ri],[li+1,ri+1][l_i,r_i],[l_{i+1},r_{i+1}] 合并为区间 [li,ri+1][l_i,r_{i+1}],这样 N(S)N(S) 不变,但 SS 不减。一定是不劣的。

    考虑用一个简单的形式刻画 iN(S)bi\sum_{i \in N(S)}b_i,可以写成所有区间减去相邻区间交。两个部分的表示都不难,修改后的变化容易表示。

    可以直接上线段树转移,维护 f0/1,0/1f_{0/1,0/1} 表示目前区间左端点选/不选,右端点选/不选的最大值。转移时枚举一下中点怎么选就好了。

    需要对坐标离散化一下。时间复杂度 O(qlogq)\mathcal{O}\big(q\log q\big),空间复杂度 O(q)\mathcal{O}(q)

    #include<bits/stdc++.h>
    #define vector basic_string
    #define int long long
    #define rd read()
    #define gc pa == pb && (pb = (pa = buf) + fread(buf, 1, 100000, stdin), pa == pb) ? EOF : *pa++
    using namespace std;
    static char buf[100000], * pa(buf), * pb(buf);
    inline int read(){
    	register int x=0,s=gc;while(!isdigit(s))s=gc;
    	while(isdigit(s))x=(x<<1)+(x<<3)+(s^48),s=gc;
    	return x;
    }
    const int N=500005,inf=1e16;
    int n,q,L;
    struct query{
    	int op,x,v;
    }t[N];
    vector<int> v;
    struct seg{
    	int f[N<<2][2][2],w[N<<2],t[N<<2];
    	inline void chkmax(int &x,int y){
    		x=x<y?y:x;
    	}
    	inline void pushup(int id){
    		for(int i:{0,1})for(int j:{0,1})f[id][i][j]=-inf;
    		for(int l1:{0,1})for(int r1:{0,1})
    			for(int l2:{0,1})for(int r2:{0,1})
    				chkmax(f[id][l1][r2],
    					f[id<<1][l1][r1]+f[id<<1|1][l2][r2]+(r1&&l2)*w[id]);}
    	inline void push(int id,int k){
    		t[id]+=k,w[id]+=k;
    		for(int i:{0,1})for(int j:{0,1})f[id][i][j]-=k;
    		chkmax(f[id][0][0],0);
    	}
    	inline void pushdown(int id){
    		if(t[id])push(id<<1,t[id]),push(id<<1|1,t[id]),t[id]=0;
    	}
    	inline void U(int id,int l,int r,int x,int k){
    		if(l==r)return f[id][1][1]+=k,void();
    		int mid=l+r>>1;pushdown(id);
    		x<=mid?U(id<<1,l,mid,x,k):U(id<<1|1,mid+1,r,x,k),pushup(id);
    	}
    	inline void U(int id,int l,int r,int x,int y,int k){
    		if(x>y)return;if(x<=l&&y>=r)return push(id,k);
    		int mid=l+r>>1;pushdown(id);
    		if(x<=mid)U(id<<1,l,mid,x,y,k);
    		if(y>mid)U(id<<1|1,mid+1,r,x,y,k);
    		if(x<=mid&&y>mid)w[id]+=k;pushup(id);
    	}
    	inline int res(){
    		return max({f[1][0][0],f[1][0][1],f[1][1][0],f[1][1][1]});
    	}
    }T;
    signed main(){
    	q=rd,L=rd;for(int i=1;i<=q;++i)t[i]={rd,rd,rd},v+=t[i].x;
    	sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end()),n=v.size();
    	for(int i=1,l,r,ans=0;i<=q;++i){
    		if(t[i].op==1)
    			l=lower_bound(v.begin(),v.end(),t[i].x)-v.begin()+1,
    			T.U(1,1,n,l,t[i].v),ans+=t[i].v;
    		else
    			l=lower_bound(v.begin(),v.end(),t[i].x-L)-v.begin()+1,
    			r=upper_bound(v.begin(),v.end(),t[i].x+L)-v.begin(),
    			T.U(1,1,n,l,r,t[i].v);
    		cout<<ans-T.res()<<'\n';
    	}
    	return 0;
    }
    
    • 1

    [JOIST 2022] 蚂蚁与方糖 / Ants and Sugar

    信息

    ID
    7224
    时间
    4000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者