P5029

P5029 T'ill It's Over

给定 n 个 1,用要求的操作使得其中尽可能多的数变成 k
m 个不同操作,其中每个操作有限定次数 l
操作分为四种类型:

  1. 给出 a,b,把一个值为 a 的数变成 b
  2. 给出 a1,a2,b,把一个值在 [a1,a2] 范围内的数变成 b
  3. 给出 a,b1,b2,把一个值为 a 的数变成在 [b1,b2] 范围内的一个数。
  4. 给出 a1,a2,b1,b2,把一个值在 [a1,a2] 范围内的数变成在 [b1,b2] 范围内的一个数。

容易发现,对于每个数的最优决策相同。
因此可以想到网络流,把 n 作为源点的流量即可。
对于每个在 [1,k] 范围内的值建一个点,其中源点连 1,汇点连 k,流量为 n

看到有区间连边的操作,所以要用到线段树优化建图,把所有操作看成是两个区间的连边,然后线段树加虚点优化建边即可。
线段树的父子节点之间连流量无穷大的边。

一定要注意是在 k 上开线段树。

点数 O(4×k+m),边数 O(mlog2k),因为数据随机,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;
}
posted @   AIskeleton  阅读(33)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示