网络流套主席树。
这是一次模拟赛vfleaking大神出的题目,网络流套主席树。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; #define inf 0x3fffffff int n; #define N 520000 int e[N],v[N],ne[N],u[N]; int nn=1; void add(int x,int y,int uu){ ne[++nn]=e[x],e[x]=nn,v[nn]=y,u[nn]=uu; } void Add(int x,int y,int uu){ // cout<<"ADD"<<x<<" "<<y<<" "<<uu<<endl; add(x,y,uu); add(y,x,0); } int ta[N],tb[N]; int nod[6000]; struct P{ int a,b,w,l,r,p; int id; bool operator<(P x)const{ return a<x.a; } }B[6000],C[6000]; int in[6000]; int tot; ll ans; int change(int p,int L,int R,int l){ int k=++tot; ta[k]=ta[p],tb[k]=tb[p]; if(L==R){ Add(C[l].id*2-1,k,inf); return k; } int m=L+R>>1; if(m>=l)ta[k]=change(ta[k],L,m,l); else tb[k]=change(tb[k],m+1,R,l); if(ta[k])Add(ta[k],k,inf); if(tb[k])Add(tb[k],k,inf); return k; } void Ask(int l,int r,int k,int L,int R,int p){ if(!k)return; if(L>=l&&R<=r){ Add(k,p,inf); return; } int m=L+R>>1; if(L<=r&&l<=m)Ask(l,r,ta[k],L,m,p); if(m+1<=r&&l<=R)Ask(l,r,tb[k],m+1,R,p); } int S,T; int ch[N]; int q[N],he,bo; int zeng(int x,int mm){ if(x==T)return mm; int k,r=mm; for(int i=e[x];i&&r;i=ne[i])if(ch[v[i]]==ch[x]+1&&u[i]){ k=zeng(v[i],min(r,u[i])); u[i]-=k; u[i^1]+=k; r-=k; } if(mm==r)ch[x]=-1; return mm-r; } bool bfs(){ int x; q[he=bo=1]=S; for(int i=1;i<=T;i++)ch[i]=-1; ch[S]=0; while(he>=bo){ x=q[bo++]; for(int i=e[x];i;i=ne[i])if(ch[v[i]]==-1&&u[i]){ ch[v[i]]=ch[x]+1; q[++he]=v[i]; } } return ch[T]!=-1; } ll dinic(){ int tt; ll r=0; while(bfs())while(tt=zeng(S,inf))r+=tt; return r; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d%d%d%d",&B[i].a,&B[i].b,&B[i].w,&B[i].l,&B[i].r,&B[i].p); C[i]=B[i]; C[i].id=i; ans+=B[i].b+B[i].w; } tot=n*2; sort(C+1,C+n+1); for(int i=1;i<=n;i++)in[C[i].id]=i; for(int i=1;i<=n;i++){ nod[i]=change(nod[i-1],1,n,in[i]); } /*for(int i=1;i<=n;i++){ cout<<C[i].a<<" "; } cout<<endl;*/ for(int i=1;i<=n;i++){ int ll=0,rr=n+1; // cout<<"i="<<i<<" "; while(ll+1!=rr){ int mid=ll+rr>>1; if(C[mid].a>=B[i].l)rr=mid; else ll=mid; } int L=rr,R; ll=0,rr=n+1; while(ll+1!=rr){ int mid=ll+rr>>1; if(C[mid].a<=B[i].r)ll=mid; else rr=mid; } R=ll; // cout<<L<<" "<<R<<endl; if(R>=L)Ask(L,R,nod[i-1],1,n,i*2); } S=tot+1; T=S+1; for(int i=1;i<=n;i++)Add(S,i*2-1,B[i].w),Add(i*2-1,T,B[i].b),Add(i*2,i*2-1,B[i].p); ans-=dinic(); cout<<ans; }