【bzoj3218】a+b Problem 最小割+主席树

【bzoj3218】a+b Problem 最小割+主席树

数据范围:$n≤5000$,$a,l,r≤10^9$,$b,w,p≤2\times 10^5$。

我们考虑一种暴力的最小割做法:

首先令$sum=\sum\limits_{i=1}^{n} b_i+w_i$

我们建一个图:

$S->i$,边权为$w_i$

$i->T$,边权为$b_i$

$i->i'$,边权为$p_i$

$j->i'$,边权为$∞$,(这里的i和j需要满足题目中的i,j限制)

然后我们对这个图跑一遍最小割,将$sum$减去这个值输出就是答案了。

这么建图总共需要$2n+2$个点,$O(n^2)$条边

 #include<bits/stdc++.h>
#define M 1000005
#define N 150005
#define INF 19890604
using namespace std; struct edge{int u,v,next;}e[M]={}; int head[N]={},use=;
void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
void ADD(int x,int y,int z){add(x,y,z); add(y,x,);} int dis[N]={},S,T; queue<int> q; bool bfs(){
memset(dis,,sizeof(dis));
q.push(S); dis[S]=;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];~i;i=e[i].next)
if(e[i].v&&dis[e[i].u]==){
dis[e[i].u]=dis[u]+;
q.push(e[i].u);
}
}
return dis[T];
} int dfs(int x,int flow){
if(x==T) return flow; int sum=;
for(int i=head[x];~i;i=e[i].next)
if(e[i].v&&dis[x]+==dis[e[i].u]){
int k=dfs(e[i].u,min(flow,e[i].v));
e[i].v-=k; e[i^].v+=k;
sum+=k; flow-=k;
if(flow==) return sum;
}
if(flow==) dis[x]=-;
return sum;
} int dinic(){
int res=;
while(bfs())
res+=dfs(S,<<);
return res;} int n,sum=;
int a[N]={},b[N]={},w[N]={},l[N]={},r[N]={},p[N]={},ok[N]={}; int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",a+i,b+i,w+i,l+i,r+i,p+i);
sum+=b[i]+w[i];
}
S=,T=*n+;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++) ADD(S,i,w[i]),ADD(i,T,b[i]),ADD(i+n,i,p[i]);
for(int i=;i<=n;i++) for(int j=;j<i;j++)
if(l[i]<=a[j]&&a[j]<=r[i])
ADD(j,i+n,INF);
cout<<sum-dinic()<<endl;
}

暴力

然后这个做法显然是会MLE的

我们发现原先的限制条件相当于在二维平面上框出一个允许的区间。

对于这种约束,我们可以用主席树来实现约束。

然后随便搞一搞就没了,注意细节

 #include<bits/stdc++.h>
#define M 400000
#define INF 19890604
using namespace std; struct edge{int u,v,next;}e[M]={}; int head[M]={},use=;
void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
void ADD(int x,int y,int z){add(x,y,z); add(y,x,);} int dis[M]={},S,T; queue<int> q; bool bfs(){
memset(dis,,sizeof(dis));
q.push(S); dis[S]=;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];~i;i=e[i].next)
if(e[i].v&&dis[e[i].u]==){
dis[e[i].u]=dis[u]+;
q.push(e[i].u);
}
}
return dis[T];
} int dfs(int x,int flow){
if(x==T) return flow; int sum=;
for(int i=head[x];~i;i=e[i].next)
if(e[i].v&&dis[x]+==dis[e[i].u]){
int k=dfs(e[i].u,min(flow,e[i].v));
e[i].v-=k; e[i^].v+=k;
sum+=k; flow-=k;
if(flow==) return sum;
}
if(flow==) dis[x]=-;
return sum;
} int dinic(){int res=; while(bfs()) res+=dfs(S,<<); return res;} int c[M]={},a[M]={},b[M]={},w[M]={},l[M]={},r[M]={},p[M]={};
int lc[M]={},rc[M]={},cnt,rt=,sum=,n; void updata(int x,int l,int r,int ll,int rr,int id){
if(!x) return;
if(ll<=l&&r<=rr)return ADD(x,id,INF);
int mid=(l+r)>>;
if(ll<=mid) updata(lc[x],l,mid,ll,rr,id);
if(mid<rr) updata(rc[x],mid+,r,ll,rr,id);
}
void updata(int &x,int l,int r,int id,int k){
cnt++; lc[cnt]=lc[x]; rc[cnt]=rc[x];
if(x) ADD(x,cnt,INF); x=cnt;
ADD(k,x,INF);
if(l==r) return;
int mid=(l+r)>>;
if(id<=mid) updata(lc[x],l,mid,id,k);
else updata(rc[x],mid+,r,id,k);
} int main(){
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",a+i,b+i,w+i,l+i,r+i,p+i);
c[i]=a[i]; sum+=b[i]+w[i];
}
sort(c+,c+n+);
for(int i=;i<=n;i++){
a[i]=lower_bound(c+,c+n+,a[i])-c;
l[i]=lower_bound(c+,c+n+,l[i])-c;
r[i]=upper_bound(c+,c+n+,r[i])-c-;
}
S=; T=*n+; cnt=*n+;
for(int i=;i<=n;i++){
ADD(S,i,w[i]);
ADD(i,T,b[i]);
ADD(i+n,i,p[i]);
if(l[i]<=r[i]) updata(rt,,n,l[i],r[i],i+n);
updata(rt,,n,a[i],i);
}
cout<<sum-dinic()<<endl;
}
上一篇:【转】Spring、Spring MVC、MyBatis整合文件配置详解


下一篇:Spring MVC、MyBatis整合文件配置详解