BZOJ #3218. a + b Problem
题面传送门
看到黑白染色啪的一下一个网络流很快啊就码上去了。
具体的,连边\((S,i,b_i),(i,T,w_i)\)。然后跑最小割就好了。
但是现在有P的限制。
考虑对于每个点建立一个虚点\(i+n\),连边\((i,i+n,P_i)\),同时对于每个满足条件的\(j\)连边\((i+n,j,INF)\),这样的话如果有一个没有被割掉白边,就会算P的答案。
但是这样建图是\(O(n^2)\)的没法过。
建图是一段区间,所以可以直接硬上主席树优化建图,就把边变成\(O(nlogn)\)级别的了。
然后直接跑dicnic就好了。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 100000
#define M 30000
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,A[N+5],cnt,L[N+5],R[N+5],S,T,x,y,z,Ne[N+5],Ans,Ns[N+5],Nh,d[N+5];const int INF=1e9;
struct yyy{int to,w,z;}tmp;struct ljb{int head,h[N+5];yyy f[N+5<<3];I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}}s;
I void con(int x,int y,int z){s.add(x,y,z);s.add(y,x,0);}queue<int> Q;
I int bfs(){
RI i;while(!Q.empty()) Q.pop();Q.push(S);Me(d,0x3f);d[S]=0;Ns[S]=s.h[S];while(!Q.empty())for(x=Q.front(),Q.pop(),i=s.h[x];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]<1e9) continue;d[tmp.to]=d[x]+1;Q.push(tmp.to);Ns[tmp.to]=s.h[tmp.to];if(tmp.to==T) return 1;
}return 0;
}
I int dfs(int x,int sum){
if(x==T) return sum;yyy tmp;RI i,pus=0,k;for(i=Ns[x];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]!=d[x]+1) continue;Ns[x]=i;k=dfs(tmp.to,min(sum,tmp.w));if(!k) d[tmp.to]=1e9;s.f[i].w-=k;s.f[i^1].w+=k;sum-=k;pus+=k;if(!sum) break;
}return pus;
}
namespace PT{
#define ls son[now][0]
#define rs son[now][1]
int Ro,son[N+5][2],cnt;I void MC(int &now,int cnt){memcpy(son[cnt],son[now],sizeof(son[cnt]));}
I void Ins(int x,int Id,int &now,int l=1,int r=Nh){MC(now,++cnt);con(cnt,now,INF);con(cnt,Id,INF);now=cnt;if(l==r)return;int m=l+r>>1;x<=m?Ins(x,Id,ls,l,m):Ins(x,Id,rs,m+1,r);}
I void Find(int x,int y,int Id,int now,int l=1,int r=Nh){if(!now) return;if(x<=l&&r<=y) return con(Id,now,INF);int m=l+r>>1;x<=m&&(Find(x,y,Id,ls,l,m),0);y>m&&(Find(x,y,Id,rs,m+1,r),0);}
#undef ls
#undef rs
}
int main(){
freopen("1.in","r",stdin);
RI i,j;scanf("%d",&n);S=0;T=2*n+1;Me(s.h,-1);for(i=1;i<=n;i++)scanf("%d%d%d%d%d%d",&A[i],&x,&y,&L[i],&R[i],&z),Ans+=x+y,con(S,i,x),con(i,T,y),con(i,i+n,z),Ne[++Nh]=A[i],Ne[++Nh]=L[i],Ne[++Nh]=R[i];
sort(Ne+1,Ne+Nh+1);Nh=unique(Ne+1,Ne+Nh+1)-Ne-1;for(i=1;i<=n;i++) A[i]=lower_bound(Ne+1,Ne+Nh+1,A[i])-Ne,L[i]=lower_bound(Ne+1,Ne+Nh+1,L[i])-Ne,R[i]=lower_bound(Ne+1,Ne+Nh+1,R[i])-Ne;
PT::cnt=2*n+1;for(i=1;i<=n;i++) PT::Find(L[i],R[i],i+n,PT::Ro),PT::Ins(A[i],i,PT::Ro);
//for(i=1;i<=n;i++) for(j=1;j<i;j++) L[i]<=A[j]&&A[j]<=R[i]&&(con(i+n,j,1e9),0);
while(bfs()) Ans-=dfs(S,INF);printf("%d\n",Ans);
}