zoukankan      html  css  js  c++  java
  • 【NOI2015】小园丁和老司机

    题面

    https://www.luogu.org/problem/P2304

    题解

    $orz$ $aysn$

    神仙题不会,还是$aysn$教我的。

    二合一。

    第一问是个$dp$,我一开始想建$DAG$跑最长路,后来经题解点化可以把同一层的一起考虑,这样就能做到$O(n)$了。

    方法:

    $f[x]$:假设新到了$x$(这一层的其他点都没有访问),允许向同一层的其他点转移,点$x$向后的最长路。
    $g[x]$:要离开$x$,不允许向同一层的其他点转移,点$x$向后的最长路。

    然后$O(n^2)->O(n)$(单调队列都不用,直接记录前缀后缀$max$就行了)

    第二问是上下界网络流

    $S$向每个点连$INF$边,每个点向$T$连$INF$边,在保留“可能留下非左右方向车辙印”的边,下界为1。

    发现边只有下界没有上界,把第一次调整略去,直接让有盈余的点流向$T$,$S$流向缺流入的点(直观理解),在代码上直接建流过后的反边就可以了。

    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100050
    #define INF 1000000007
    #define ri register int
    using namespace std;
    
    int f[N],g[N];
    int nxtf[N],nxtg[N];
    int n,x[N],y[N],id[N];
    int r1[N],c1[N],r2[N],c2[N],r3[N],c3[N],r4[N],c4[N];
    vector<int> ph1[N],ph2[N],ph3[N],ph4[N];
    bool vis[N];
    
    bool cmp1(int a,int b) {
      return y[a]<y[b] || (y[a]==y[b]&&x[a]<x[b]);
    }
    bool cmp2(int a,int b) {
      return x[a]+y[a]<x[b]+y[b] || (x[a]+y[a]==x[b]+y[b]&&y[a]<y[b]);
    }
    bool cmp3(int a,int b) {
      return x[a]-y[a]<x[b]-y[b] || (x[a]-y[a]==x[b]-y[b]&&y[a]<y[b]);
    }
    bool cmp4(int a,int b) {
      return x[a]<x[b] || (x[a]==x[b]&&y[a]<y[b]);
    }
    
    int dp(int x);
    
    int predp(int x) {
      if (g[x]!=-1) return g[x];
      int r,c,ans=0;
      r=r2[x],c=c2[x];
      if (c+1<ph2[r].size() && dp(ph2[r][c+1])+1>ans) {
        ans=f[ph2[r][c+1]]+1;
        nxtg[x]=ph2[r][c+1];
      }
      r=r3[x],c=c3[x];
      if (c+1<ph3[r].size() && dp(ph3[r][c+1])+1>ans) {
        ans=f[ph3[r][c+1]]+1;
        nxtg[x]=ph3[r][c+1];
      }
      r=r4[x],c=c4[x];
      if (c+1<ph4[r].size() && dp(ph4[r][c+1])+1>ans) {
        ans=f[ph4[r][c+1]]+1;
        nxtg[x]=ph4[r][c+1];
      }
      g[x]=ans;
      return ans;
    }
    
    int dp(int x) {
      if (f[x]!=-1) return f[x];
      int r=r1[x],n=ph1[r].size(),curm,curp;
      for (ri i=0;i<n;i++) {
        f[ph1[r][i]]=predp(ph1[r][i]);
        nxtf[ph1[r][i]]=ph1[r][i];
      }
      curm=-1000000007;curp=-1;
      for (ri i=0;i<n;i++) {
        if (curm+n-1>f[ph1[r][i]]) f[ph1[r][i]]=curm+n-1,nxtf[ph1[r][i]]=curp;
        if (g[ph1[r][i]]-i>curm) curm=g[ph1[r][i]]-i,curp=ph1[r][i];
      }
      curm=-1000000007; curp=-1;
      for (ri i=n-1;i>=0;i--) {
        if (curm>f[ph1[r][i]]) f[ph1[r][i]]=curm,nxtf[ph1[r][i]]=curp;
        if (g[ph1[r][i]]+i>curm) curm=g[ph1[r][i]]+i,curp=ph1[r][i];
      }
      return f[x];
    }
    
    void print(int x,bool s) {
      if (s==0) {
        int y=nxtf[x];
        int r=r1[y],c=c1[y];
        if (c1[x]<c) {
          for (ri i=c1[x]-1;i>=0;i--) printf("%d ",ph1[r][i]);
          for (ri i=c1[x]+1;i<=c;i++) printf("%d ",ph1[r][i]);
        }
        else if (c1[x]>c) {
          for (ri i=c1[x]+1;i<ph1[r].size();i++) printf("%d ",ph1[r][i]);
          for (ri i=c1[x]-1;i>=c;i--) printf("%d ",ph1[r][i]);
        }
        print(y,1);
      }
      else if (s==1) {
        int y=nxtg[x];
        if (!y) return;
        printf("%d ",y);
        print(y,0);
      }
    }
    
    int dis(int x,int y) {
      if (c1[x]<c1[y]) return c1[y];
      return ph1[r1[x]].size()-c1[y]-1;
    }
    
    struct graph {
      vector<int> ed[N],w,to;
      int d[N],cur[N],p[N];
      #define S (n+1)
      #define T 0
      void add_edge(int u,int v,int tw) {
        to.push_back(v); w.push_back(INF); ed[u].push_back(to.size()-1);
        to.push_back(u); w.push_back(0);   ed[v].push_back(to.size()-1);
      }
      void add_edges(int u,int v,int tw){
        to.push_back(v); w.push_back(tw);  ed[u].push_back(to.size()-1);
        to.push_back(u); w.push_back(INF); ed[v].push_back(to.size()-1);
      }
      bool bfs() {
        queue<int> q;
        memset(d,0x3f,sizeof(d));
        d[S]=0; q.push(S);
        while (!q.empty()) {
          int x=q.front(); q.pop();
          for (ri i=0;i<ed[x].size();i++) {
            int e=ed[x][i];
            if (d[x]+1<d[to[e]] && w[e]) {
              d[to[e]]=d[x]+1;
              q.push(to[e]);
            }
          }
        }
        return d[T]<INF;
      }
      int dfs(int x,int limit) {
        if (x==T || limit==0) return limit;
        int sum=0; 
        for (ri &i=cur[x];i<ed[x].size();i++) {
          int e=ed[x][i];
          if (w[e] && d[x]+1==d[to[e]]) {
            int f=dfs(to[e],min(limit,w[e]));
            if (!f) continue;
            sum+=f; limit-=f; 
            w[e]-=f; w[1^e]+=f;
            if (!limit) return sum;
          }
        }
        return sum;
      }
      int dinic() {
        int ret=0;
        while (bfs()) {
          memset(cur,0,sizeof(cur));
          ret+=dfs(S,INF);
        }
        return ret;
      }
      int work() {
        for (ri i=0;i<to.size();i+=2) {
          p[to[1^i]]--;
          p[to[i]]++;
        }
        int flow=0;
        for (ri i=1;i<=n;i++) {
          if (p[i]>0) {
            add_edges(n+1,i,p[i]);
            flow+=p[i];
          }
          else if (p[i]<0) {
            add_edges(i,0,-p[i]);
          }
        }
        flow-=dinic();
        return flow;
      }
    } G;
    
    void redp(int x,int s) {
      if (vis[x+s*n]) return;
      vis[x+s*n]=1;
      if (s==0) {
        if (f[x]==g[x]) redp(x,1);
        int n=ph1[r1[x]].size();
        for (ri i=0;i<n;i++) if (i!=c1[x]) {
          if (f[x]-g[ph1[r1[x]][i]]==dis(x,ph1[r1[x]][i])) redp(ph1[r1[x]][i],1);
        }
      }
      else {
        int r,c,ans=0;
        r=r2[x],c=c2[x];
        if (c+1<ph2[r].size() && g[x]==f[ph2[r][c+1]]+1) {
          G.add_edge(x,ph2[r][c+1],INF);
          redp(ph2[r][c+1],0);
        }
        r=r3[x],c=c3[x];
        if (c+1<ph3[r].size() && g[x]==f[ph3[r][c+1]]+1) {
          G.add_edge(x,ph3[r][c+1],INF);
          redp(ph3[r][c+1],0);
        }
        r=r4[x],c=c4[x];
        if (c+1<ph4[r].size() && g[x]==f[ph4[r][c+1]]+1) {
          G.add_edge(x,ph4[r][c+1],INF);
          redp(ph4[r][c+1],0);
        }
      }
    }
    
    int main() {
      int cc;
      scanf("%d",&n);
      for (ri i=1;i<=n;i++) scanf("%d %d",&x[i],&y[i]);
      for (ri i=1;i<=n;i++) id[i]=i;
    
      ri i,j;
      sort(id,id+n+1,cmp1);
      cc=0;
      for (i=0;i<=n;i+=j) {
        ++cc;
        for (j=0;y[id[i+j]]==y[id[i]]&&i+j<=n;j++) {
          ph1[cc].push_back(id[i+j]);
          r1[id[i+j]]=cc;
          c1[id[i+j]]=j;
        }
      }
      
      sort(id,id+n+1,cmp2);
      cc=0;
      for (i=0;i<=n;i+=j) {
        ++cc;
        for (j=0;x[id[i+j]]+y[id[i+j]]==x[id[i]]+y[id[i]]&&i+j<=n;j++) {
          ph2[cc].push_back(id[i+j]);
          r2[id[i+j]]=cc;
          c2[id[i+j]]=j;
        }
      }
      
      sort(id,id+n+1,cmp3);
      cc=0;
      for (i=0;i<=n;i+=j) {
        ++cc;
        for (j=0;x[id[i+j]]-y[id[i+j]]==x[id[i]]-y[id[i]]&&i+j<=n;j++) {
          ph3[cc].push_back(id[i+j]);
          r3[id[i+j]]=cc;
          c3[id[i+j]]=j;
        }
      }
      
      sort(id,id+n+1,cmp4);
      cc=0;
      for (i=0;i<=n;i+=j) {
        ++cc;
        for (j=0;x[id[i+j]]==x[id[i]]&&i+j<=n;j++) {
          ph4[cc].push_back(id[i+j]);
          r4[id[i+j]]=cc;
          c4[id[i+j]]=j;
        }
      }
      memset(f,-1,sizeof(f));
      memset(g,-1,sizeof(g));
      printf("%d
    ",dp(0));
      print(0,0); puts("");
      redp(0,0);
      printf("%d
    ",G.work()); 
      return 0;
    }
  • 相关阅读:
    Hadoop中Combiner的使用
    Pig与Hive的区别
    HiveQL(HiveSQL)跟普通SQL最大区别一直使用PIG,而今也需要兼顾HIVE
    pig hive 区别
    Hadoop生态上几个技术的关系与区别:hive、pig、hbase 关系与区别
    js打包和加密
    直观的链式回调 MyPromise
    SequelizeConnectionError: Client does not support authentication protocol requested by server; consider upgrading MariaDB client
    Lost connection to MySQL server at 'reading initial communication packet',system error:0
    css display flex
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11285659.html
Copyright © 2011-2022 走看看