方糖

· · 题解

方糖并不想被吃掉,所以(迟到地)给大家送来方糖社的新春祝福:

求最大匹配,利用扩展霍尔定理:一个任意二分图 (V1,V2,E),最大匹配为 |V1|-\max_{S \in V1}(|S|-|N(S)|)|V1| 即为 \sum [T_i=1]A_iS 即为一些区间的蚂蚁的并,设为 \cup [l_i,r_i],那么 N(S) 即为这些区间向两边扩展 L 的区间的并,设为 \cup [l_i-L,r_i+L]。两个相邻区间间隔大于 2L,否则将两个区间合并为一个区间更优。

$$\sum \sum_{j=l_i}^{r_i}a_j-\sum_{j=l_i-L}^{r_i+L}s_j=\sum \sum_{j=l_i}^{r_i}(a_j-\sum_{k=j-L}^{j+L}s_k)+\sum_{j=l_i}^{r_i-1}\sum_{k=j-L+1}^{j+L}s_k$$ 令 $j \in [l_i,r_i]$ 表示 $j$ 被选择,设 $dp_{l,r,0/1,0/1}$ 表示区间 $[l,r]$ 左端点和右端点是否被选择时的最大值。可以用线段树进行维护,同时为了合并左右儿子,对于每个区间 $(l,r,mid)$ 还需要维护 $$\sum_{k=mid-L+1}^{mid+L}s_k $$ 的值。修改时注意 $dp_{l,r,0,0} \geq 0$。 加入蚂蚁时,对 $X_i$ 位置单点加即可。 加入方糖时,会影响 $[X_i-L,X_i+L]$ 这个区间的 dp 值。具体地,如果区间 $(l,r,mid) \subseteq [X_i-L,X_i+L]$,那么 dp 值均会减少,而 $$\sum_{k=mid-L+1}^{mid+L}s_k $$ 的值会增加。此外,如果 $X_i-L\leq mid < X_i+L$,那么该区间的 $$\sum_{k=mid-L+1}^{mid+L}s_k $$ 值也会增加。 实现需要离散化。 ```cpp #include<bits/stdc++.h> #define int long long #define lc p<<1 #define rc p<<1|1 using namespace std; const int N=5e5+5,inf=0x0d0007210d000721; struct tree{ int l,r,val,tag; int dp[2][2]; }t[N*4]; void pushup(int p){ for(int x=0;x<=1;x++){ for(int y=0;y<=1;y++){ t[p].dp[x][y]=-inf; } } for(int x1=0;x1<=1;x1++){ for(int y1=0;y1<=1;y1++){ for(int x2=0;x2<=1;x2++){ for(int y2=0;y2<=1;y2++){ t[p].dp[x1][y2]=max(t[p].dp[x1][y2],t[lc].dp[x1][y1]+t[rc].dp[x2][y2]+(y1&x2)*t[p].val); } } } } } void add(int p,int val){ t[p].val+=val; t[p].tag+=val; for(int x=0;x<=1;x++){ for(int y=0;y<=1;y++){ t[p].dp[x][y]-=val; } } t[p].dp[0][0]=max(t[p].dp[0][0],0ll); } void pushdown(int p){ if(t[p].tag){ add(lc,t[p].tag); add(rc,t[p].tag); t[p].tag=0; } } void build(int p,int l,int r){ t[p].l=l,t[p].r=r; if(l==r){ return; } int mid=(t[p].l+t[p].r)>>1; build(lc,l,mid); build(rc,mid+1,r); } void addg(int p,int x,int y){ if(t[p].l==t[p].r){ t[p].dp[1][1]+=y; return; } pushdown(p); int mid=(t[p].l+t[p].r)>>1; if(x<=mid){ addg(lc,x,y); } else{ addg(rc,x,y); } pushup(p); } void addf(int p,int l,int r,int x){ if(l>r){ return; } if(l<=t[p].l&&t[p].r<=r){ add(p,x); return; } pushdown(p); int mid=(t[p].l+t[p].r)>>1; if(l<=mid){ addf(lc,l,r,x); } if(mid+1<=r){ addf(rc,l,r,x); } if(l<=mid&&mid+1<=r){ t[p].val+=x; } pushup(p); } int Q,L; int lsh[N],lshcnt; struct opt{ int t,x,a; }o[N]; int ans; signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>Q>>L; lshcnt=1; for(int i=1;i<=Q;i++){ cin>>o[i].t>>o[i].x>>o[i].a; if(o[i].t==1){ lsh[++lshcnt]=o[i].x; } } sort(lsh+1,lsh+lshcnt+1); lshcnt=unique(lsh+1,lsh+lshcnt+1)-lsh-1; build(1,1,lshcnt); for(int i=1;i<=Q;i++){ if(o[i].t==1){ ans+=o[i].a; int pos=lower_bound(lsh+1,lsh+lshcnt+1,o[i].x)-lsh; addg(1,pos,o[i].a); } else{ int posl=lower_bound(lsh+1,lsh+lshcnt+1,o[i].x-L)-lsh,posr=upper_bound(lsh+1,lsh+lshcnt+1,o[i].x+L)-lsh-1; addf(1,posl,posr,o[i].a); } cout<<ans-max(max(t[1].dp[0][0],t[1].dp[0][1]),max(t[1].dp[1][0],t[1].dp[1][1]))<<'\n'; } return 0; } ```