http://acm.hdu.edu.cn/showproblem.php?pid=5009

题目要求对空序列染成目标颜色序列,对一段序列染色的成本是不同颜色数的平方。

这题我们显然会首先想到用DP去解决,dp[i] = min( dp[i] , dp[j] + cost(i , j) )。但是枚举ij的复杂的高达n^2,不能接受,我们就考虑去优化它。

首先比较容易想到的是,去除连续重复元素,可以把它们当作同一个点处理。

此外在遍历j的过程中如果当前序列颜色不同的数量平方大于当前dp[i],显然已经没有一并涂色以及继续扩充序列的必要了(随着序列数的增长,不同颜色的数量是单调递增的,必然在之后不会出现小于dp[i]的情况。

但是这样并不能把复杂的降低至sqrt(n)*n,因为我们枚举的子序列会有重复元素,所以并不是每次j的变化都会来带不同颜色数的增长,比如24242424这种。那么我们考虑这种情况该如何优化,我们先换一个比较容易理解的例子9871341,当我们的i指向最后一个1的时候,我们的j开始向前遍历,当遍历到上一个i的时候,其实我们已经知道,这个i我们把它包含进去是没有成本的(因为之前已经有1了,并不会使不同颜色的数增加)所以我们应该不假思索地加入这个数。但是计算机是很蠢的,它每次依旧会遍历到它,别看这遍历一个单位很快,像24242424这种就会导致计算机大量重复地枚举了。为此我们模拟一个双向链表,在枚举i地过程中,我们维护前缀序列地链表全都是不同的元素,这个实现起来其实并不难,因为i每次增长最多会增加一个重复元素,相应的我们也只需要去除一个重复元素(即上一次出现当前值的那个位置)。然后在遍历j的时候只需要遍历链表就好了。这样我们保证j遍历过程中每次都能增加一个不同颜色,复杂的自然降低到n*sqrt(n)了。

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <map>
  4. #include <set>
  5. #include <vector>
  6. #include <cstdio>
  7. #define LL int
  8. using namespace std;
  9. const int N=;
  10. const LL inf=1e8+;
  11. LL arr[N];
  12. LL dp[N];
  13. int pre[N];
  14. int nex[N];
  15. int main()
  16. {
  17. cin.sync_with_stdio(false);
  18. int n;
  19. while(cin>>n)
  20. {
  21. int p=;
  22. for(int i=; i<n; i++)
  23. {
  24. int c;
  25. //c=_read();
  26. cin>>c;
  27. if(i==||arr[p]==c)
  28. arr[p]=c;
  29. else
  30. arr[++p]=c;
  31. }
  32. map<LL,int> unq;
  33. int rk=;
  34. for(int i=; i<=p; i++)
  35. {
  36. map<LL,int>::iterator it=unq.find(arr[i]);
  37. if(it!=unq.end())
  38. arr[i]=it->second;
  39. else
  40. {
  41. unq[arr[i]]=rk;
  42. arr[i]=rk;
  43. rk++;
  44. }
  45. pre[i]=i-;
  46. nex[i]=i+;
  47. }
  48. dp[p+]=;
  49. map<LL,int> v;
  50. for(int i=p; i>=; i--)
  51. {
  52. LL ans=inf;
  53. if(v.find(arr[i])==v.end())
  54. v[arr[i]]=i;
  55. else
  56. {
  57. int ix=v[arr[i]];
  58. nex[pre[ix]]=nex[ix];
  59. pre[nex[ix]]=pre[ix];
  60. v[arr[i]]=i;
  61. }
  62. int rx;
  63. int cnt=;
  64. for(int j=i; j!=p+; j=nex[j])
  65. {
  66. //cout<<j<<endl;
  67. cnt++;
  68. LL p2=cnt*cnt;
  69. if(p2>ans)
  70. break;
  71. if(p2+dp[nex[j]]<ans)
  72. {
  73. ans=p2+dp[nex[j]];
  74. rx=j;
  75. }
  76. //ans=min(ans,(LL)(xx+dp[j+1]));
  77. //cout<<ans<<' '<<s.size()<<' '<<dp[j+1]<<endl;
  78. }
  79. dp[i]=ans;
  80. //cout<<dp[i]<<' '<<i<<' '<<rx<<endl;
  81. }
  82. //printf("%d\n",dp[0]);
  83. cout<<dp[]<<endl;
  84. }
  85. return ;
  86. }

hdu-5009 Paint Pearls DP+双向链表 with Map实现去重优化的更多相关文章

  1. HDU - 5009 Paint Pearls(dp+优化双向链表)

    Problem Description Lee has a string of n pearls. In the beginning, all the pearls have no color. He ...

  2. HDU 5009 Paint Pearls 双向链表优化DP

    Paint Pearls Problem Description   Lee has a string of n pearls. In the beginning, all the pearls ha ...

  3. HDU 5009 Paint Pearls(西安网络赛C题) dp+离散化+优化

    转自:http://blog.csdn.net/accelerator_/article/details/39271751 吐血ac... 11668627 2014-09-16 22:15:24 A ...

  4. HDU 5009 Paint Pearls (动态规划)

    Paint Pearls Problem Description Lee has a string of n pearls. In the beginning, all the pearls have ...

  5. hdu 5009 Paint Pearls

    首先把具有相同颜色的点缩成一个点,即数据离散化. 然后使用dp[i]表示涂满前i个点的最小代价.对于第i+1个点,有两种情况: 1)自己单独涂,即dp[i+1] = dp[i] + 1 2)从第k个节 ...

  6. HDU-5009 Paint Pearls 动态规划 双向链表

    题目链接:https://cn.vjudge.net/problem/HDU-5009 题意 给一串序列,可以任意分割多次序列,每次分割的代价是被分割区间中的数字种数. 求分割区间的最小代价.n< ...

  7. HDOJ 5009 Paint Pearls

    Dicripntion Lee has a string of n pearls. In the beginning, all the pearls have no color. He plans t ...

  8. AC日记——Paint Pearls hdu 5009

    Paint Pearls 思路: 离散化+dp+剪枝: dp是个n方的做法: 重要就在剪枝: 如果一个长度为n的区间,有大于根号n种颜色,还不如一个一个涂: 来,上代码: #include <c ...

  9. hdu5009 Paint Pearls (DP+模拟链表)

    http://acm.hdu.edu.cn/showproblem.php?pid=5009 2014网络赛 西安 比较难的题 Paint Pearls Time Limit: 4000/2000 M ...

随机推荐

  1. Eclipse 02: 安装spring tool suite插件

    在实际项目开发时,如果我们创建了一个spring文件,其实也就是个xml文件,如果没有集成spring的开发工具,创建的就是一个单纯的xml文件.安装spring插件以后创建spring配置文件会方便 ...

  2. IIC - 【转载】对I2C总线的时钟同步和总线仲裁的深入理解

    对I2C总线的时钟同步和总线仲裁的深入理解 每一个IIC总线器件内部的SDA.SCL引脚电路结构都是一样的,引脚的输出驱动与输入缓冲连在一起.其中输出为漏极开路的场效应管.输入缓冲为一只高输入阻抗的同 ...

  3. git操作常见错误处理

    1.Error:The authenticity of host 'github.com (192.30.255.112)' can't be established. Git密钥认证github时出 ...

  4. 高性能Nginx服务器-负载均衡

    Location正则表达式 location的作用 location指令的作用是根据用户请求的URI来执行不同的应用,也就是根据用户请求的网站URL进行匹配,匹配成功即进行相关的操作. locatio ...

  5. Centos下搭建邮件服务器

    一.协议 SMTP:用于发送邮件 POP3:用于接收邮件,接收后会将服务器上邮件删除 IMAP:用于接收邮件,接收后不会删除服务器邮件 二.几个重要的角色 MUA:可以理解为收取邮件的工具,比如thu ...

  6. js篇-判断数组对象中是否含有某个值,并返回该条数据

    项目背景需求是: 已知: var a=[{name:'jenny',age:18},{name:'john',age:19},{name:'jack',age:20}] var b ='jenny' ...

  7. C#:特性

    #define IsText//添加一个宏,接触注释 using System; using System.Collections.Generic; using System.Diagnostics; ...

  8. netframework webapi exceptionless

    1.webapi项目 添加nuget    exceptionless webapi 2.在exceptionless server端添加项目,注意key 3.修改api项目的webconfig &l ...

  9. How Many Triangles (极角排序 + 尺取法)

    题意:二维平面与有很多个点,然后求构成锐角三角形的个数. 思路:对于每一个三角形我们知道存在至少2个锐角,只要有一个钝角就不行了,所以我们的想法就是枚举所有夹角的状态,然后得知情况,确定用总个数减去- ...

  10. 虚拟机centos7配置本地yum源

    在虚拟机中要使用yum命令,就要先配置一下yum源,下面就分享一下这个过程: 1. 挂载iso到vmware,首先得确保CD/DVD连接到镜像.可以这样操作 2. 执行下面的命令 # mkdir /m ...