$ans=\sum_{color_i=black}\ b_i+\sum_{color_i=white}\ w_i-\sum_{i=abnormal}\ p_i$
把它转化一下
$ans=\sum_{i=1}^{n}(b_i+w_i)-\sum_{color_i=black}\ w_i-\sum_{color_i=white}\ b_i-\sum_{i=abnormal}\ p_i$
这不是最小割--最大权闭合子图的套路吗!
设$S$割为黑点集合,$T$割为白点集合
怎么处理奇怪的方格?套路地把$i$拆成$i_1,i_2$
对于每个点$i$:
$links(S,i_1,b_i),link(i_1,T,w_i),link(i_1,i_2,p_i)$
对于每个$j
于是你就可以AC拿到部分分辣!
但是由于出题人毒瘤的搞大数据,还需要优化
注意到每次连边时$j$都需要枚举,复杂度$O(n^2)$
考虑用主席树把复杂度降到$(nlogn)$
先把所有$a_i,l_i,r_i$拿来搞一遍离散化做主席树的下标
处理到点$i$时,先在主席树上查询$[l_i,r_i]$包含的区间,直接把$i_2$连到那个区间上去,$link(i_2,o,inf)$
蓝后再把点$i$按$a_i$加入到主席树上包含$a_i$的区间内,$link(o,i_1,inf)$
别忘了和上个版本连起来$link(o,p,inf)$
最终:$ans=\sum_{i=1}^{n}(b_i+w_i)-dinic()$
#include#include #include #include #include using namespace std; typedef long long ll; #define N 100005 #define M 2000005 const int inf=2e9; int n,S,T,cur[N],d[N]; ll ans; int m,b[N],L[N],R[N],A[N]; int u,rt[N],lc[N],rc[N]; queue <int> h; bool vis[N]; int cnt=1,hd[N],nxt[M],ed[N],poi[M];ll val[M]; inline void adde(int x,int y,int v){ nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt, ed[x]=cnt, poi[cnt]=y, val[cnt]=v; } inline void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);} bool bfs(){ for(int i=1;i<=u;++i) vis[i]=0,cur[i]=hd[i]; h.push(S); vis[S]=1; while(!h.empty()){ int x=h.front(); h.pop(); for(int i=hd[x];i;i=nxt[i]){ int to=poi[i]; if(!vis[to]&&val[i]>0) vis[to]=1,d[to]=d[x]+1,h.push(to); } }return vis[T]; } ll dfs(int x,ll a){ if(x==T||a==0) return a; ll F=0,f; for(int &i=cur[x];i;i=nxt[i]){ int to=poi[i]; if(d[to]==d[x]+1&&(f=dfs(to,min(a,val[i])))>0) a-=f,F+=f,val[i]-=f,val[i^1]+=f; if(!a) break; }return F; } ll dinic(){ll re=0; while(bfs())re+=dfs(S,inf); return re;} #define mid (l+r)/2 void Add(int &o,int p,int l,int r,int v){ o=++u; if(p)link(o,p,inf); link(o,v,inf);//加入到包含a_v的区间 if(l==r) return; if(A[v]<=mid) Add(lc[o],lc[p],l,mid,v),rc[o]=rc[p]; else Add(rc[o],rc[p],mid+1,r,v),lc[o]=lc[p]; } void Ask(int o,int l,int r,int x1,int x2,int v){ if(!o) return ; if(x1<=l&&r<=x2) {link(v+n,o,inf); return;} if(x1<=mid) Ask(lc[o],l,mid,x1,x2,v); if(x2>mid) Ask(rc[o],mid+1,r,x1,x2,v); } int main(){ scanf("%d",&n); S=n*2+1; T=S+1; u=T+1; for(int i=1,B,W,P;i<=n;++i){ scanf("%d%d%d%d%d%d",&A[i],&B,&W,&L[i],&R[i],&P); ans+=B+W; b[++m]=A[i]; b[++m]=L[i]; b[++m]=R[i]; link(S,i,B); link(i,T,W); link(i,i+n,P); }sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1;//离散化 for(int i=1;i<=n;++i){ A[i]=lower_bound(b+1,b+m+1,A[i])-b; L[i]=lower_bound(b+1,b+m+1,L[i])-b; R[i]=lower_bound(b+1,b+m+1,R[i])-b; Ask(rt[i-1],1,m,L[i],R[i],i); Add(rt[i],rt[i-1],1,m,i); }printf("%lld",ans-dinic()); return 0; }