zoukankan      html  css  js  c++  java
  • CF889 E Mod Mod Mod——DP

    题目:http://codeforces.com/contest/889/problem/E

    这题真好玩。

    官方题解说得很好。

    想到相邻 a[ i ] 之间的段可能可以一起维护,但是不太会。

    原来是表示成 i*x+k 的形式。其中 x 是具体的值,放在 DP 数组里只要记录 “ x<= ... 的 x 都满足这个式子” 就行,因为每次经过一个 i ,范围都是保留最底部的一些之类的。

    然后写了一个不行的代码。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define ll long long
    using namespace std;
    ll rdn()
    {
      ll ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    ll Mx(ll a,ll b){return a>b?a:b;}
    const int N=2e5+5,M=N*20;
    int n,tot,l[N],r[N];ll a[N],dp[M],dy[M],ans;
    map<ll,int> mp[N];
    int main()
    {
      n=rdn();
      for(int i=1;i<=n;i++)a[i]=rdn();
      r[1]=++tot; dp[tot]=0; dy[tot]=a[1]-1;
      for(int i=1;i<n;i++)
        {
          l[i+1]=r[i]=tot;
          for(int j=l[i]+1,d;j<=r[i];j++)
        {
          ll k=dp[j],r=dy[j],tp=r%a[i+1];
          if(r>=a[i+1])
            {
              if(!mp[i+1].count(a[i+1]-1))
            {
              mp[i+1][a[i+1]-1]=++tot;
              dy[tot]=a[i+1]-1;
            }
              d=mp[i+1][a[i+1]-1];
              dp[d]=Mx(dp[d],k+i*(r-tp-a[i+1]));
            }
          if(!mp[i+1].count(tp))
            {
              mp[i+1][tp]=++tot; dy[tot]=tp;
            }
          d=mp[i+1][tp];
          dp[d]=Mx(dp[d],k+i*(r-tp));
        }
        }
      for(int i=l[n]+1;i<=tot;i++)
        {
          ll k=dp[i],r=dy[i];
          ans=Mx(ans,n*r+k);
        }
      printf("%lld
    ",ans);
      return 0;
    }
    View Code

    不能遍历 r 没有变的位置。也不能让它们占用更多空间,比如在 i 处用一个位置、又在 i+1 处用一个位置。

    然后抄了一番题解。原来 map 可以这样遍历。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define ll long long
    using namespace std;
    ll rdn()
    {
      ll ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    ll Mx(ll a,ll b){return a>b?a:b;}
    const int N=2e5+5;
    int n;ll a[N],ans;
    map<ll,ll> mp;
    map<ll,ll>::iterator it;
    int main()
    {
      n=rdn();for(int i=1;i<=n;i++)a[i]=rdn();
      mp[a[1]-1]=0;
      for(int i=1;i<n;i++)
        {
          while(1)
        {
          it=mp.end(); it--;
          ll r=(*it).first, k=(*it).second;
          if(r<a[i+1])break;
          mp.erase(it);
          mp[a[i+1]-1]=Mx(mp[a[i+1]-1],k+i*(r-r%a[i+1]-a[i+1]));
          mp[r%a[i+1]]=Mx(mp[r%a[i+1]],k+i*(r-r%a[i+1]));
        }
        }
      for(it=mp.begin();it!=mp.end();it++)
        ans=Mx(ans,n*(*it).first+(*it).second);
      printf("%lld
    ",ans);
      return 0;
    }
  • 相关阅读:
    剑指Offer-11.二进制中1的个数(C++/Java)
    剑指Offer-10.矩形覆盖(C++/Java)
    剑指Offer-9.变态跳台阶(C++/Java)
    UVA 1608 Non-boring sequence 不无聊的序列(分治,中途相遇)
    UVA1607 Gates 与非门电路 (二分)
    UVA 1451 Average平均值 (数形结合,斜率优化)
    UVA 1471 Defense Lines 防线 (LIS变形)
    UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
    UVA 11134 FabledRooks 传说中的车 (问题分解)
    UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
  • 原文地址:https://www.cnblogs.com/Narh/p/11014805.html
Copyright © 2011-2022 走看看