UOJ#77 bzoj3218 a + b Problem 可持久化线段树优化建图+网络流
来源:互联网 发布:石家庄软件学院 编辑:程序博客网 时间:2024/06/01 08:39
题目大意:
有n个点,如果第i点染黑得到bi的收益,染白得wi的收益。
每个点有属性ai,li,ri,pi。
如果第i个点染成黑色,并且存在一个点j满足
第j个点染白色,j< i 且 li<=aj<=ri
则i为奇怪的点,付出pi的代价。
求总收益最大。
n<=1e5
题目分析:
可以看出一个网络流的模型。
从源点向每个点连bi,每个点向汇点连wi。
对于第i个点,新建一个结点,从i向这个结点连pi,然后从这个点向所有能使i变成奇怪的点的结点连INF。
用所有b和w的和减去最大流即是答案。
但是n太大了,我们发现这样建边是n^2的。
所以需要优化一下。
我们对于所有的ai建一棵线段树,在叶子结点向对应的点连INF,其他结点向儿子连INF。
然后对于每个点,只要在线段树上查询l~r,然后连INF就行了。
但是由于要求 j < i ,所以把线段树可持久化一下。新建的结点向上一个版本的结点连INF即可。
然后点和边就都变成nlogn级别的了。
代码如下:
#include <cstdio>#include <iostream>#define MAXN 1000000000#define MAXM 5200#define N 520000#define M 1200000using namespace std;const int INF=0x3f3f3f3f;inline int Min(int x,int y) { return x<y?x:y; }int n,S,T,ans;int fir[N],nes[M],v[M],q[M],tot=1;int dl[N],d[N],b[MAXM],w[MAXM];struct segment{ segment *ch[2]; int id; void* operator new (size_t size,segment *x);}*root[MAXM];void* segment :: operator new(size_t size,segment *x){ static segment *C=NULL,*mempool=NULL; if(C==mempool) mempool=(C=new segment[1<<15])+(1<<15); if(x==NULL) C->ch[0]=C->ch[1]=NULL; else C->ch[0]=x->ch[0],C->ch[1]=x->ch[1]; C->id=T++; return C++;}void edge(int x,int y,int z){ v[++tot]=y; q[tot]=z; nes[tot]=fir[x]; fir[x]=tot;}void Edge(int x,int y,int z){ edge(x,y,z); edge(y,x,0);}void update(segment *&c,int l,int r,int x,int y){ int tmp=c?c->id:0; c=new (c) segment; if(tmp) Edge(c->id,tmp,INF); Edge(c->id,y,INF); if(l==r) { Edge(c->id,y,INF); return; } int mid=l+r>>1; if(x<=mid) update(c->ch[0],l,mid,x,y),Edge(c->id,c->ch[0]->id,INF); else update(c->ch[1],mid+1,r,x,y),Edge(c->id,c->ch[1]->id,INF);}void query(segment *c,int l,int r,int x,int y){ if(c==NULL) return; if(x<=l && y>=r) { Edge(T,c->id,INF); return; } int mid=l+r>>1; if(x<=mid) query(c->ch[0],l,mid,x,y); if(y>mid) query(c->ch[1],mid+1,r,x,y);}bool bfs(){ static int c; int l=1,r=1; for(int i=S;i<=T;i++) d[i]=0; d[S]=1; dl[1]=S; while(l<=r) { c=dl[l++]; for(int t=fir[c];t;t=nes[t]) { if(!q[t] || d[v[t]]) continue; d[v[t]]=d[c]+1; dl[++r]=v[t]; if(v[t]==T) return true; } } return false;}int dfs(int c,int flow){ if(c==T || flow==0) return flow; int ans=0,tmp; for(int t=fir[c];t;t=nes[t]) { if(!q[t] || d[v[t]]!=d[c]+1) continue; tmp=dfs(v[t],Min(q[t],flow)); q[t]-=tmp; q[t^1]+=tmp; flow-=tmp; ans+=tmp; if(!flow) break; } if(!ans) d[c]=-1; return ans;}int dinic(){ int ans=0; while(bfs()) ans+=dfs(S,INF); return ans;}int main(){ scanf("%d",&n); T=n+1; for(int i=1,a,l,r,p;i<=n;i++) { scanf("%d%d%d%d%d%d",&a,&b[i],&w[i],&l,&r,&p); Edge(i,T,p); query(root[i-1],0,MAXN,l,r); T++; root[i]=root[i-1]; update(root[i],0,MAXN,a,i); } for(int i=1;i<=n;i++) { Edge(S,i,b[i]); Edge(i,T,w[i]); ans+=b[i]+w[i]; } printf("%d\n",ans-dinic()); return 0;}
阅读全文
0 0
- UOJ#77 bzoj3218 a + b Problem 可持久化线段树优化建图+网络流
- 【网络流+可持久化线段树】[UOJ#77/BZOJ3218]A+B Problem
- [BZOJ3218][UOJ#77]A+B Problem(可持久化线段树+最小割)
- BZOJ 3218 a + b Problem 网络流 可持久化线段树优化建图
- BZOJ 3218|UOJ 77|A + B Problem|最大流|可持久化线段树
- BZOJ3218 UOJ#77 A+B Problem(最小割+主席树)
- 【线段树】【树】【网络流】[UOJ#77]A+B Problem
- BZOJ 3218 a + b Problem 最大流 + 可持久化线段树
- [bzoj3218]a + b Problem
- bzoj3218: a + b Problem
- BZOJ3218: A + B Problem
- BZOJ 3218 a + b Problem 可持久化线段树+最小割
- bzoj 3218: a + b Problem (可持久化线段树+最小割)
- bzoj 3218: a + b Problem 最小割+可持久化线段树
- bzoj 3489: A simple rmq problem 可持久化线段树套可持久化线段树
- 【bzoj3218】 a + b Problem 最小割+主席树
- BZOJ 3218/UOJ #77 a + b Problem
- 【UOJ #218. 【UNR #1】】火车管理 可持久化线段树
- PHP本地进行API接口测试
- 混合APP开发之5+API上传图片过大导致上传失败的解决方式
- Java排序方法sort的使用详解
- 使用hive、java api两种方式实现wordcount功能、及个人感悟
- 30天自制操作系统-第7天笔记
- UOJ#77 bzoj3218 a + b Problem 可持久化线段树优化建图+网络流
- CSDN日报20170630——《降薪求职,到底该不该?》
- vim编辑器的使用总结
- 使用xcode查看和提高单元测试覆盖率
- 6 亿推送数据告诉你,我们的一天究竟在干嘛
- TensorFlow与OpenCV,读取图片,进行简单操作并显示
- Go语言学习之image、image/color、image/png、image/jpeg包(the way to go)
- chrome浏览器调试JS代码
- Bluetooth的使用