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;
    }
  • 相关阅读:
    部署NetCore项目(本文介绍用用IIS部署)
    vs中添加MySql实体集流程
    一文搞定HashMap的实现原理
    二分查找
    hashcode返回值可能为负数
    哈希碰撞与生日攻击
    并发的第二天
    java并发编程-1
    排序的第一天
    并发的第一天
  • 原文地址:https://www.cnblogs.com/Narh/p/11014805.html
Copyright © 2011-2022 走看看