首页 > 代码库 > bzoj 3218: a + b Problem

bzoj 3218: a + b Problem

Description

 

技术分享

技术分享

Input

Output

Sample Input

Sample Output

HINT

Source 

传说中的可持久化线段树优化网络流。。。

做了一些预备题后最小割建图还是比较简单,但边数是n^2。

每次可以通过向值域中的区间连边,使边数降为nlogn,要满足j<i,打一个可持久化,每次搞完再insert即可

蒯一个PoPoQQQ大爷的图,很清楚啊。。。

技术分享

 

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define RG register
using namespace std;
typedef long long ll;
const int N=1000050;
const int Inf=19260817;
int gi(){
  int x=0,flag=1;
  char ch=getchar();
  while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) flag=-1;ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
  return x*flag;
}
int head[N],nxt[N],to[N],s[N],cnt=1,level[N],q[N],S,T,F;
int a[5050],b[5050],w[5050],l[5050],r[5050],p[5050],n,tot;
int sz,ls[100050],rs[100050],root[100050],hsh[100050],sum,goal,hh=0;
inline void Addedge(RG int x,RG int y,RG int z) {
  to[++cnt]=y,s[cnt]=z,nxt[cnt]=head[x],head[x]=cnt;
}
inline void lnk(RG int x,RG int y,RG int z){
  if(!x||!y) return;
  Addedge(x,y,z),Addedge(y,x,0);
}
inline bool bfs(){
  for(RG int i=1;i<=sz;i++) level[i]=0;
  q[0]=S,level[S]=1;int t=0,sum=1;
  while(t<sum){
    int x=q[t++];
    if(x==T) return 1;
    for(RG int i=head[x];i;i=nxt[i]){
      int y=to[i];
      if(s[i]&&level[y]==0){
	level[y]=level[x]+1;
	q[sum++]=y;
      }
    }
  }
  return 0;
}
inline int dfs(RG int x,int maxf){
  if(x==T) return maxf;
  int ret=0;
  for(RG int i=head[x];i;i=nxt[i]){
    int y=to[i],f=s[i];
    if(level[y]==level[x]+1&&f){
      int minn=min(f,maxf-ret);
      f=dfs(y,minn);
      s[i]-=f,s[i^1]+=f,ret+=f;
      if(ret==maxf) break;
    }
  }
  if(!ret) level[x]=0;
  return ret;
}
inline void Dinic(){
  while(bfs()) F+=dfs(S,Inf);
}
inline void insert(int l,int r,int x,int &y,int v){
  y=++sz;ls[y]=ls[x],rs[y]=rs[x];hh++;
    lnk(x,y,Inf);lnk(goal,y,Inf);
    if(l==r) return;
    int mid=(l+r)>>1;
    if(v<=mid) insert(l,mid,ls[x],ls[y],v);
    else insert(mid+1,r,rs[x],rs[y],v);
}
inline void query(int x,int L,int R,int xl,int xr){
  if(!x) return;
  if(xl<=L&&R<=xr){lnk(x,goal,Inf);return;}
  int mid=(L+R)>>1;
  if(xl<=mid) query(ls[x],L,mid,xl,xr);
  if(xr>mid) query(rs[x],mid+1,R,xl,xr);
}
int main(){
  n=gi();S=2*n+1;T=2*n+2;sz=T;
  for(RG int i=1;i<=n;i++){
    a[i]=gi(),b[i]=gi(),w[i]=gi(),l[i]=gi(),r[i]=gi(),p[i]=gi();
    tot+=b[i],tot+=w[i];hsh[++sum]=a[i];
  }
  sort(hsh+1,hsh+1+sum);sum=unique(hsh+1,hsh+sum+1)-hsh-1;
  for(int i=1;i<=n;i++){
    a[i]=lower_bound(hsh+1,hsh+1+sum,a[i])-hsh;
    l[i]=lower_bound(hsh+1,hsh+1+sum,l[i])-hsh;
    r[i]=upper_bound(hsh+1,hsh+1+sum,r[i])-hsh-1;
    lnk(S,i,w[i]);lnk(i,T,b[i]);lnk(i+n,i,p[i]);
  }
  for(int i=1;i<=n;i++){
    goal=i+n;if(l[i]<=r[i]) query(root[i-1],1,sum,l[i],r[i]);
    goal=i;insert(1,sum,root[i-1],root[i],a[i]);
  }
  Dinic();printf("%d\n",tot-F);
  return 0;
}

  

bzoj 3218: a + b Problem