ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P5029

2022-05-26 13:33:45  阅读:199  来源: 互联网

标签:right r1 int t2 t1 P5029 op


P5029 T'ill It's Over

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

  1. 给出 \(a,b\),把一个值为 \(a\) 的数变成 \(b\)。
  2. 给出 \(a_1,a_2,b\),把一个值在 \(\left[ a_1,a_2 \right]\) 范围内的数变成 \(b\)。
  3. 给出 \(a,b_1,b_2\),把一个值为 \(a\) 的数变成在 \(\left[ b_1,b_2 \right]\) 范围内的一个数。
  4. 给出 \(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;
}

标签:right,r1,int,t2,t1,P5029,op
来源: https://www.cnblogs.com/AIskeleton/p/16313133.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有