题解:P12463 [Ynoi Easy Round 2018] 星野瑠美衣
littlez_meow · · 题解
下面认为
先来研究
数轴上我们把权值为
-
当
x<\min\{x_1,x_2\} ,变化量为-|x_1-x_2|+x_1+x_2-2x+v ; -
当
\min\{x_1,x_2\}\le x\le \max\{x_1,x_2\} ,变化量为v ; -
当
x>\max\{x_1,x_2\} ,变化量为-|x_1-x_2|-x_1-x_2+2x+v 。
画图发现,我们可以不管前提条件,直接对这三个式子取
再加上
那么就可以进行费用流建模了。
我们一共有五类点:源点
有如下四类容量均为
点数边数都是
直接费用流跑不过去,考虑模拟费用流,我们每次找一条增广路。
这张图是二分图,左部点有
那么直接维护任意两个左部点之间经过一个右部点的最长路,以这个为边权在左部点内部跑 SPFA,找出来增广路后暴力修改影响到的路径。我们维护任意两个左部点之间经过一个右部点的所有路径,每次增广是把
时间复杂度
代码
#include<bits/stdc++.h>
#define File(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define ll long long
#define F(i,a,b) for(int i(a),i##i##end(b);i<=i##i##end;++i)
#define R(i,a,b) for(int i(a),i##i##end(b);i>=i##i##end;--i)
#define fi first
#define se second
using namespace std;
const int MAXN=2e5+1;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m,px[MAXN],py[MAXN],x[MAXN],y[MAXN],v[MAXN];
//S->0,T->10
priority_queue<pair<ll,int> >q[11][11],del[11][11];
ll ans,val[11][MAXN],dis[11][11],dep[11];
int dir[11][MAXN],fr[11];
inline void era(int u,int mid,int v){
F(i,0,10) if(dir[i][mid]*dir[u][mid]==-1){
if(dir[u][mid]==1) del[u][i].emplace(val[u][mid]+val[i][mid],mid);
else del[i][u].emplace(val[u][mid]+val[i][mid],mid);
}
F(i,0,10) if(i!=u&&dir[i][mid]*dir[v][mid]==-1){
if(dir[v][mid]==-1) del[i][v].emplace(val[v][mid]+val[i][mid],mid);
else del[v][i].emplace(val[v][mid]+val[i][mid],mid);
}
}
inline void add(int u,int mid,int v){
F(i,0,10) if(dir[i][mid]*dir[v][mid]==-1){
if(dir[v][mid]==1) q[v][i].emplace(val[v][mid]+val[i][mid],mid);
else q[i][v].emplace(val[v][mid]+val[i][mid],mid);
}
F(i,0,10) if(i!=v&&dir[i][mid]*dir[u][mid]==-1){
if(dir[u][mid]==-1) q[i][u].emplace(val[u][mid]+val[i][mid],mid);
else q[u][i].emplace(val[u][mid]+val[i][mid],mid);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
F(i,1,n) cin>>px[i]>>py[i];
px[n+1]=px[1],py[n+1]=py[1];
F(i,1,m) cin>>x[i]>>y[i]>>v[i];
F(i,1,m){
val[0][i]=v[i],dir[0][i]=1;
val[10][i]=-INF;
F(j,1,9){
dir[j][i]=-1;
switch((j-1)/3){
case 0:{val[j][i]-=2*x[i];break;}
case 2:{val[j][i]+=2*x[i];break;}
}
switch(j%3){
case 1:{val[j][i]-=2*y[i];break;}
case 0:{val[j][i]+=2*y[i];break;}
}
}
}
F(i,1,n){
val[0][i+m]=-INF;
val[10][i+m]=-abs(px[i]-px[i+1])-abs(py[i]-py[i+1]),dir[10][i+m]=-1;
F(j,1,9){
dir[j][i+m]=1;
switch((j-1)/3){
case 0:{val[j][i+m]+=px[i]+px[i+1];break;}
case 1:{val[j][i+m]+=abs(px[i]-px[i+1]);break;}
case 2:{val[j][i+m]+=-px[i]-px[i+1];break;}
}
switch(j%3){
case 1:{val[j][i+m]+=py[i]+py[i+1];break;}
case 2:{val[j][i+m]+=abs(py[i]-py[i+1]);break;}
case 0:{val[j][i+m]+=-py[i]-py[i+1];break;}
}
}
}
F(i,1,m) F(j,1,9) q[0][j].emplace(val[0][i]+val[j][i],i);
F(i,1,n) F(j,1,9) q[j][10].emplace(val[10][i+m]+val[j][i+m],i+m);
F(i,1,n) ans+=abs(px[i]-px[i+1])+abs(py[i]-py[i+1]);
F(k,1,n){
F(i,0,10) F(j,0,10){
while(!q[i][j].empty()&&!del[i][j].empty()&&q[i][j].top()==del[i][j].top()) q[i][j].pop(),del[i][j].pop();
if(q[i][j].empty()) dis[i][j]=-INF;
else dis[i][j]=q[i][j].top().fi;
}
memset(dep,-0x3f,sizeof(dep));
static bool isin[11];
queue<int>qu;
qu.push(0);
dep[0]=0,isin[0]=1;
while(!qu.empty()){
int now=qu.front();
qu.pop();isin[now]=0;
F(i,0,10) if(dep[i]<dep[now]+dis[now][i]){
dep[i]=dep[now]+dis[now][i],fr[i]=now;
if(!isin[i]) isin[i]=1,qu.push(i);
}
}
ans+=dep[10];
cout<<ans<<" ";
int now=10,tp=0;
static int u[11],v[11],mid[11];
while(now){
int i=fr[now],t=q[i][now].top().se;
era(i,t,now);
++tp,u[tp]=i,mid[tp]=t,v[tp]=now;
now=i;
}
R(i,tp,1) dir[u[i]][mid[i]]*=-1,dir[v[i]][mid[i]]*=-1,val[u[i]][mid[i]]*=-1,val[v[i]][mid[i]]*=-1;
while(tp) add(u[tp],mid[tp],v[tp]),--tp;
}
return 0;
}