XSY3244 10.31 D

XSY3244 10.31 D

题意:

​ 数轴上有\(N\)只老鼠\(M\)个洞,每个洞有一个容量,求所有老鼠进洞的最小代价。(\(N,M\leq1000000\),时限\(2s\))

题解:

​ 被代爷的前两道题卡得醉生梦死,场上根本没看这题。。。

​ 十万的档显然可以\(dp\),加个线段树什么的就可以了。

​ 对于100%的数据,上面的那个\(dp\)已经没用了,代爷给的做法是正反贪心,让每只老鼠贪心选择左/右最近的洞。对于每只老鼠,这两个洞正好是它最终决策会去的洞。然后把老鼠和每一个可能有老鼠进的洞一起摆在数轴上,做一遍\(dp\)。状态\(f_{i,j}\)表示搞到第\(i\)个点,老鼠比洞多\(j\)个,转移挺简单的。这个\(dp\)相较上面的那个,优点在于它可以直接利用指针跳\(O(1)\)转移。时空复杂度都是线性的。

​ 场上还有人想出了另一种做法。这是我代码的做法。

​ 我们建出一个模型:

  • 对于老鼠和洞,我们分别用两个大根堆\(M,H\)储存,按位置。

  • 将老鼠和洞按位置排序。

  • 如果当前处理的是老鼠,那就取\(H\)堆顶,钦定它进这个洞,这个容量\(-1\)并且在以老鼠为镜面,这个洞反射过去的地方往\(M\)堆里插入一只老鼠,更新答案。

  • 如果当前处理的是洞,那就让\(M\)堆中所有坐标比它大的老鼠滚进这个洞(显然比老鼠在当前洞内更优),但是这不一定最优,所以我们要建立反悔机制:\(\Delta = 当前洞的坐标-这只老鼠的坐标\),在\(当前洞坐标当前洞坐标+ \Delta\)的地方新建容量为一的洞;更新答案,如果处理完所有之后当前洞还有剩余的容量,就把它扔进堆里。想一想,为什么。

    ​代码:

    #include
    #include
    #include
    #include
    #include
    #define fo(i,l,r) for(int i=l;i<=r;i++)
    #define of(i,l,r) for(int i=l;i>=r;i--)
    #define fe(i,u) for(int i=head[u];i;i=e[i].next)
    using namespace std;
    typedef long long ll;
    typedef pair pli;
    #define P(a,b) make_pair(a,b)
    inline void open(const char *s)
    {
      #ifndef ONLINE_JUDGE
      char str[20];
      sprintf(str,"in%s.txt",s);
      freopen(str,"r",stdin);
    //    sprintf(str,"out%s.txt",s);
    //    freopen(str,"w",stdout);
      #endif
    }
    inline ll rd()
    {
      static ll x,f;
      x=0;f=1;
      char ch=getchar();
      for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1ll;
      for(;ch>='0'&&ch<='9';ch=getchar())x=x*10ll+ch-'0';
      return f>0?x:-x;
    }
    const int N=1000010;
    int n,m;
    ll ans=0;
    pli a[N<<1];
    priority_queueM;
    priority_queueH;
    
    inline void gaoM(pli x)
    {
      ll res=1000000000000000ll;
      if(!H.empty()){
          pli y=H.top();H.pop();
          res=x.first-y.first;
          if(--y.second)H.push(y);
      }
      M.push(x.first+res);
      ans+=res;
    }
    inline void gaoH(pli x)
    {
      while(x.second&&!M.empty()&&M.top()>x.first){
          ll y=M.top();M.pop();
          ll res=x.first-y;x.second--;
          ans+=res;H.push(P(x.first+res,1));
      }
      if(x.second)H.push(x);
    }
    
    int main()
    {
      open("c");
      n=rd();m=rd();
      fo(i,1,n)a[i].first=rd(),a[i].second=-1;
      ll s=0;
      fo(i,1,m)a[n+i].first=rd(),a[n+i].second=rd(),s+=a[n+i].second;
      if(s

转载于:https://www.cnblogs.com/JackyhhJuRuo/p/9884190.html

你可能感兴趣的:(XSY3244 10.31 D)