【BZOJ3218】a + b Problem
题解:思路很简单,直接最小割。S->i,容量为Bi;i->T,容量为Wi;所有符合条件的j->new,容量inf;new->i,容量Pi。
但是符合条件的j有很多,并且限制有二维,所以用可持久化线段树优化建图即可。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <algorithm> using namespace std; int n,nm,cnt,tot,S,T,ans; struct node { int a,b,w,l,r,p; }p[5010]; struct NUM { int val,org,k; }num[15010]; int ls[100000],rs[100000],rt[5010],ref[5010]; int d[100000],head[100000],next[3000000],val[3000000],to[3000000]; queue<int> q; void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++; } void insert(int x,int &y,int l,int r,int a,int b) { y=++tot; if(l==r) { if(x) add(x,y,1<<30); add(b,y,1<<30); return ; } int mid=l+r>>1; if(a<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,a,b); else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,a,b); if(ls[y]) add(ls[y],y,1<<30); if(rs[y]) add(rs[y],y,1<<30); } void query(int x,int l,int r,int a,int b,int c) { if(!x||a>b) return ; if(a<=l&&r<=b) { add(x,c,1<<30); return; } int mid=l+r>>1; if(a<=mid) query(ls[x],l,mid,a,b,c); if(b>mid) query(rs[x],mid+1,r,a,b,c); } int dfs(int x,int mf) { if(x==T) return mf; int i,k,temp=mf; for(i=head[x];i!=-1;i=next[i]) { if(d[to[i]]==d[x]+1&&val[i]) { k=dfs(to[i],min(temp,val[i])); if(!k) d[to[i]]=0; val[i]-=k,val[i^1]+=k,temp-=k; if(!temp) break; } } return mf-temp; } int bfs() { int i,u; while(!q.empty()) q.pop(); memset(d,0,sizeof(d)); q.push(S),d[S]=1; while(!q.empty()) { u=q.front(),q.pop(); for(i=head[u];i!=-1;i=next[i]) { if(!d[to[i]]&&val[i]) { d[to[i]]=d[u]+1; if(to[i]==T) return 1; q.push(to[i]); } } } return 0; } bool cmp(NUM a,NUM b) { return a.val<b.val; } int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } int main() { n=rd(); int i,l,r,mid; for(i=1;i<=n;i++) num[i].val=rd(),p[i].w=rd(),p[i].b=rd(),p[i].l=rd(),p[i].r=rd(),p[i].p=rd(),num[i].org=i; sort(num+1,num+n+1,cmp); for(ref[0]=-1,i=1;i<=n;i++) { if(num[i].val>ref[nm]) ref[++nm]=num[i].val; p[num[i].org].a=nm; } for(i=1;i<=n;i++) { l=1,r=nm+1; while(l<r) { mid=l+r>>1; if(ref[mid]>=p[i].l) r=mid; else l=mid+1; } p[i].l=r,l=1,r=nm+1; while(l<r) { mid=l+r>>1; if(ref[mid]<=p[i].r) l=mid+1; else r=mid; } p[i].r=l-1; } S=0,T=tot=n+1; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) add(S,i,p[i].b),insert(rt[i-1],rt[i],1,nm,p[i].a,i),add(i,T,p[i].w); for(i=1;i<=n;i++) ans+=p[i].b+p[i].w,query(rt[i-1],1,nm,p[i].l,p[i].r,++tot),add(tot,i,p[i].p); while(bfs()) ans-=dfs(S,1<<30); printf("%d",ans); return 0; }