P5029
给定 \(n\) 个 1,用要求的操作使得其中尽可能多的数变成 \(k\)。
\(m\) 个不同操作,其中每个操作有限定次数 \(l\)。
操作分为四种类型:
- 给出 \(a,b\),把一个值为 \(a\) 的数变成 \(b\)。
- 给出 \(a_1,a_2,b\),把一个值在 \(\left[ a_1,a_2 \right]\) 范围内的数变成 \(b\)。
- 给出 \(a,b_1,b_2\),把一个值为 \(a\) 的数变成在 \(\left[ b_1,b_2 \right]\) 范围内的一个数。
- 给出 \(a_1,a_2,b_1,b_2\),把一个值在 \(\left[ a_1,a_2 \right]\) 范围内的数变成在 \(\left[ b_1,b_2 \right]\) 范围内的一个数。
容易发现,对于每个数的最优决策相同。
因此可以想到网络流,把 \(n\) 作为源点的流量即可。
对于每个在 \(\left[1,k\right]\) 范围内的值建一个点,其中源点连 1,汇点连 \(k\),流量为 \(n\)。
看到有区间连边的操作,所以要用到线段树优化建图,把所有操作看成是两个区间的连边,然后线段树加虚点优化建边即可。
线段树的父子节点之间连流量无穷大的边。
一定要注意是在 \(k\) 上开线段树。
点数 \(O(4\times k +m)\),边数 \(O(m \log_2 k)\),因为数据随机,dinic 跑的挺快。
#include <bits/stdc++.h>
#define MI int m=(l+r)>>1;
using namespace std;
const int N=1e6,INF=2e9;
int n,m,k,op,len,ans;
int fir[N<<1],cnt=1;struct E{int v,w,nt;}e[N<<1];
void I(int u,int v,int w=0){e[++cnt]=(E){v,w,fir[u]};fir[u]=cnt;}
void in(int u,int v,int w){I(u,v,w),I(v,u);}
int d[N<<1],cur[N<<1],st,ed;queue <int>q;
bool bfs(){
for(int i=st;i<=ed;i++)d[i]=0,cur[i]=fir[i];d[st]=1;q.push(st);
while(!q.empty()){
int u=q.front(),V;q.pop();
for(int i=fir[u];i;i=e[i].nt)
if(!d[V=e[i].v]&&e[i].w)
d[V]=d[u]+1,q.push(V);
}return d[ed];
}int dfs(int u,int fl){
if(u==ed)return fl;int ans=0,V,re;
for(int i=cur[u];i;i=e[i].nt){
cur[u]=i;if(d[V=e[i].v]==d[u]+1&&e[i].w){
re=dfs(V,min(fl,e[i].w));
e[i].w-=re,e[i^1].w+=re;fl-=re,ans+=re;
if(!fl)break;
}
}if(!ans)d[u]=0;return ans;
}void dinic(){while(bfs())ans+=dfs(st,INF);cout<<ans;}
int ls[N<<1],rs[N<<1],c,r1,r2;
void b1(int &p,int l,int r){
if(l==r){p=l;return;}p=++c;MI
b1(ls[p],l,m);b1(rs[p],m+1,r);
in(p,ls[p],INF);in(p,rs[p],INF);
}void b2(int &p,int l,int r){
if(l==r){p=l;return;}p=++c;MI
b2(ls[p],l,m);b2(rs[p],m+1,r);
in(ls[p],p,INF);in(rs[p],p,INF);
}void C(int p,int l,int r,int L,int R,int k,bool f){
if(l>=L&&r<=R){in(f?p:k,f?k:p,INF);return;}
MI if(L<=m)C(ls[p],l,m,L,R,k,f);
if(R>m)C(rs[p],m+1,r,L,R,k,f);
}
int main(){
cin>>n>>m>>k;c=k;b1(r1,1,k);b2(r2,1,k);
for(int i=1,a,b,x,y,t1,t2;i<=m;i++){
cin>>op>>len>>a>>b;t1=++c;t2=++c;
if(op==1)C(r2,1,k,a,a,t1,1),C(r1,1,k,b,b,t2,0);
else if(op==2)cin>>x,C(r2,1,k,a,b,t1,1),C(r1,1,k,x,x,t2,0);
else if(op==3)cin>>x,C(r2,1,k,a,a,t1,1),C(r1,1,k,b,x,t2,0);
else cin>>x>>y,C(r2,1,k,a,b,t1,1),C(r1,1,k,x,y,t2,0);
in(t1,t2,len);
}ed=c+1;in(st,1,n),in(k,ed,n);dinic();return 0;
}