ARC122F

太庙了太庙了

首先我们可以跑一遍单调栈使得栈中元素横坐标单增纵坐标单减。

先考虑 \(K=1\) 的情况

考虑将B向右移,将R向下移动使得符合条件,则向下移有1费,向右移有1费。

也就转化成了(假设 \(X,Y\) 有序):

  1. \(X_i\to X_{i+1}\ w=dis_x(i,i+1)\)
  2. \(Y_{i+1}\to Y_i\ w=dis_y(i,i+1)\)
  3. \(Y_i\to X_i\ w=0[i\ is\ blue ]\)

其中第三个可以代表一个断点:一开始一直向下移动,从这里开始向右移动。

答案即是求 \(Y_n\)\(X_n\)的最短路。

那么现在 \(K>1\) 了,也就是说我们可以有 \(K\) 个断点了。其实也就是多了一个边:

  1. \(X_i\to Y_{i+1}\ w=0[i\ is\ red]\)

限制每个蓝色石头只能用一次所以第三个边流量是1,其他边流量是inf。

那么我们就可以跑一个费用流求解了。

Code

听说Atcoder卡spfa于是去学了一下dij费用流,跑的还挺快的。

#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
namespace EMT{
    typedef long long ll;typedef double db;
    #define pf printf
    #define F(i,a,b) for(int i=a;i<=b;i++)
    #define D(i,a,b) for(int i=a;i>=b;i--)
    inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
    inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
    inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
    inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
    const int N=1e6+10,infi=0x3f3f3f3f;const ll infl=0x3f3f3f3f3f3f3f3f;
    int n,m,K,sx[N],sy[N],co=1,head[N],pe[N];ll dis[N],flow[N],h[N];bool vis[N];
    struct pt{int x,y;friend bool operator <(pt a,pt b){return a.x==b.x?a.y<b.y:a.x<b.x;}}p[N];
    struct dp{int x;ll v;friend bool operator <(dp a,dp b){return a.v>b.v;}};
    struct node{int next,to,w1,w2;}e[N*10];std::priority_queue<dp>q;
    inline void add(int next,int to,int w1,int w2){e[++co]={head[next],to,w1,w2},head[next]=co;}
    inline void ins(int next,int to,int w1,int w2){add(next,to,w1,w2),add(to,next,0,-w2);}
    inline void dij(int S,int T,int n){
        memset(dis,0x3f,sizeof(ll)*(n+1));dis[S]=0;
        memset(vis,0,sizeof(bool)*(n+1));flow[S]=infi;
        q.push({S,0});
        while(!q.empty()){
            int x=q.top().x;q.pop();if(vis[x])continue;vis[x]=1;
            for(int i(head[x]),j(e[i].to);i;j=e[i=e[i].next].to)if(e[i].w1){
                if(dis[j]>dis[x]+h[x]-h[j]+e[i].w2){
                    dis[j]=dis[x]+h[x]-h[j]+e[i].w2;
                    pe[j]=i;flow[j]=min(flow[x],e[i].w1);
                    q.push({j,dis[j]});
                }
            }
        }
    }
    inline ll EK(int S,int T,int n){
        dij(S,T,n);
        F(i,1,n)h[i]+=dis[i];
        ll ans=h[T];
        for(int i=T;i^S;i=e[pe[i]^1].to)
            e[pe[i]].w1--,e[pe[i]^1].w1++;
        return ans;
    }
    inline short main(){
        n=read(),m=read(),K=read();
        F(i,1,n+m)sx[i]=p[i].x=read(),sy[i]=p[i].y=read();
        std::sort(sx+1,sx+n+m+1),std::sort(sy+1,sy+n+m+1);
        sx[0]=std::unique(sx+1,sx+n+m+1)-sx-1;
        sy[0]=std::unique(sy+1,sy+n+m+1)-sy-1;
        F(i,2,sx[0])ins(i-1,i,infi,sx[i]-sx[i-1]),ins(i,i-1,infi,0);
        F(i,2,sy[0])ins(i+sx[0],i+sx[0]-1,infi,sy[i]-sy[i-1]),ins(i+sx[0]-1,i+sx[0],infi,0);
        static pt s[N];int top=0;
        std::sort(p+1,p+n+1);
        F(i,1,n){
            while(top&&s[top].y<=p[i].y)top--;
            s[++top]=p[i];
        }
        F(i,1,top)s[i].x=std::lower_bound(sx+1,sx+sx[0]+1,s[i].x)-sx,
                  s[i].y=std::lower_bound(sy+1,sy+sy[0]+1,s[i].y)-sy;
        F(i,2,top)ins(s[i-1].x,sx[0]+s[i].y,infi,0);
        F(i,n+1,n+m){
            p[i].x=std::lower_bound(sx+1,sx+sx[0]+1,p[i].x)-sx;
            p[i].y=std::lower_bound(sy+1,sy+sy[0]+1,p[i].y)-sy;
            ins(p[i].y+sx[0],p[i].x,1,0);
        }ll ans=0;
        F(i,1,K)ans+=EK(s[1].y+sx[0],s[top].x,sx[0]+sy[0]);
        pi(ans);
        return 0;
    }
}
signed main(){return EMT::main();}
posted @ 2022-06-18 11:40  letitdown  阅读(89)  评论(0编辑  收藏  举报