XXX has an array of length n. XXX wants to know that, for a given w, what is the sum of the distinct elements’ number in all substrings of length w. For example, the array is { 1 1 2 3 4 4 5 } When w = 3, there are five substrings of length 3. They are (1,1,2),(1,2,3),(2,3,4),(3,4,4),(4,4,5) 
The distinct elements’ number of those five substrings are 2,3,3,2,2. 
So the sum of the distinct elements’ number should be 2+3+3+2+2 = 12

InputThere are several test cases. 
Each test case starts with a positive integer n, the array length. The next line consists of n integers a 1,a2…a n, representing the elements of the array. 
Then there is a line with an integer Q, the number of queries. At last Q lines follow, each contains one integer w, the substring length of query. The input data ends with n = 0 For all cases, 0<w<=n<=10 6, 0<=Q<=10 4, 0<= a 1,a 2…a n <=10 6OutputFor each test case, your program should output exactly Q lines, the sum of the distinct number in all substrings of length w for each query.Sample Input

7
1 1 2 3 4 4 5
3
1
2
3
0

Sample Output

7
10
12

这真是道好题啊,dp的题 看题解理解起来真费劲。
题意:给一个序列,将其分为长度为m的集合,求每个集合的 不同元素的个数 之和。

解题思路:一开始我是想到线段树和树状数组,但是因为对这些掌握的不太熟,只会加减乘gcd,而且找不到子集和母集合直接关系,感觉是dp,但是无从下手。后来看了好久的题解,最后才明白。

题解地址:http://blog.csdn.net/a601025382s/article/details/12283581

题解内容:

题意:

给定一个序列ai,个数为n。再给出一系列w;对于每个w,求序列中,所有长度为w的连续子串中的权值和,子串权值为子串中不同数的个数

题解:

一道动态规划体。。一开始i想成了树状数组。dp[i表示w=i时所求的答案。dp[1]=n,这个很容易知道,dp[2]中的子串就是删去dp[1]中最后一个子串,再每个子串加上其之后的那个数,以此类推。。

要删去的最后一个子串的权值很好求,for以遍就能预处理,num[i]表示w=i的最后一个子串权值。难的就是求加上一个数后所加的权值:另c[i]表示一个数与它前面值相同的最近距离,这也能for一遍预处理。之后求出sum[i],表示两同值数最短距离大于等于i的值。对于dp[i-1]推dp[i],加上一个数,只有当这个数与它前面同值数最短距离大于等于i时才会加权值,否则会重复而不加。所以可以推出递推式:dp[i]=dp[i-1]-num[i-1]+sum[i],dp[1]=n;

注意:

1.处理c[i]的时候,如果一个数ai前面没有相同的数,则距离计算为到0的距离i,why?因为加上这类数也是成立。

2.答案dp[i]会超int,我就wa了好几次。。


这题的思路就是,比如集合长度len为1的时候,每个集合不同元素的个数c肯定是1,而len加1时,因为总共就n个数,集合的总数量肯定会减1,也就是最后一个集合会消失。而c是否会加,取决于新加的这个元素在集合中有没有相同的数。所以我们要预处理每个数与其前面最近的相同的数的距离,如果与最近的相同数的距离大于集合的长度,也就是说在集合外,那么把这个数加入集合c就会加1。我们把距离为i的相同数的个数存在cnt[i]数组里面。这样我们求长度为2的时候,只需要先把除了长度小于2的cnt全加上,再减去长度为1时最后一个集合的值就是答案。
所以最后的公式就是dp[i]=dp[i-1]-last[i-1]+sum[i];//sum[i]为cnt从i到n的和。
注意,这里计算记录cnt数组的时候,不需要记录距离为i的两个相同数的位置,因为这些子集把n个数完全覆盖,所以无论这两个数在哪,都会被考虑在子集中,不明白的话可以自己用一个例子模拟一下,会发现只需要记距离为i的个数有多少就行了。

 1 #include <stdio.h>
2 #include <cstring>
3 #include <iostream>
4 #include <algorithm>
5 #include <cmath>
6 #include <stack>
7 #include <queue>
8 typedef long long ll;
9 const int maxn = 1e6+5;
10 int nu[maxn],pre[maxn],cnt[maxn],sum[maxn],lt[maxn];
11 ll dp[maxn]; //dp会爆int
12 using namespace std;
13
14 int main(){
15 ios::sync_with_stdio(false);
16 int n,m,t;
17 while(cin>>n,n)
18 {
19 memset(dp,0,sizeof(dp));
20 memset(pre,0,sizeof(pre));
21 memset(cnt,0,sizeof(cnt));
22 memset(sum,0,sizeof(sum));
23 memset(lt,0,sizeof(lt));
24
25 for(int i=1;i<=n;++i) cin>>nu[i];
26
27 for(int i=1;i<=n;++i) //求出相同的值距离为i的数有多少对
28 {
29 cnt[i-pre[nu[i]]]++;
30 pre[nu[i]]=i;
31 }
32 sum[n]=cnt[n];
33 for(int i=n-1;i>=1;i--) //把cnt的和按len=n到1的顺序存在sum数组里面。便于最后操作
34 {
35 sum[i]=sum[i+1]+cnt[i];
36 }
37 memset(pre,0,sizeof(pre));
38 lt[1]=1;
39 pre[nu[n]]++;
40 for(int i=2;i<=n;++i) //记录最后一个集合的不同元素个数
41 {
42 if(pre[nu[n-i+1]])
43 lt[i]=lt[i-1];
44 else
45 {
46 lt[i]=lt[i-1]+1;
47 pre[nu[n-i+1]]=1;
48 }
49 }
50 dp[1]=n;
51 for(int i=2;i<=n;++i)
52 {
53 dp[i]=dp[i-1]+sum[i]-lt[i-1];//重点
54 }
55 cin>>m;
56 for(int i=0;i<m;++i)
57 {
58 cin>>t;
59 cout<<dp[t]<<endl;
60 }
61 }
62 return 0;
63 }

HDU - 4455 Substrings(非原创)的更多相关文章

  1. hdu 4455 Substrings(计数)

    题目链接:hdu 4455 Substrings 题目大意:给出n,然后是n个数a[1] ~ a[n], 然后是q次询问,每次询问给出w, 将数列a[i]分成若干个连续且元素数量为w的集合,计算每个集 ...

  2. HDU 4455.Substrings

    Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. hdu 4455 Substrings(找规律&DP)

    Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. hdu 4455 Substrings (DP 预处理思路)

    Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  5. HDU 4455 Substrings[多重dp]

    Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 4455 Substrings --递推+树状数组优化

    题意: 给一串数字,给q个查询,每次查询长度为w的所有子串中不同的数字个数之和为多少. 解法:先预处理出D[i]为: 每个值的左边和它相等的值的位置和它的位置的距离,如果左边没有与他相同的,设为n+8 ...

  7. HDU 4455 Substrings ( DP好题 )

    这个……真心看不出来是个DP,我在树状数组的康庄大道上欢快的奔跑了一下午……看了题解才发现错的有多离谱. 参考:http://www.cnblogs.com/kuangbin/archive/2012 ...

  8. Linux下high CPU分析心得【非原创】

    非原创,搬运至此以作笔记, 原地址:http://www.cnitblog.com/houcy/archive/2012/11/28/86801.html 1.用top命令查看哪个进程占用CPU高ga ...

  9. CSS样式命名整理(非原创)

    非原创,具体出自哪里忘了,如果侵害您的利益,请联系我. CSS样式命名整理 页面结构 容器: container/wrap 整体宽度:wrapper 页头:header 内容:content 页面主体 ...

随机推荐

  1. drf认证、节流、权限、版本

    Django rest framework 认证: 作用:验证用户是否登录 在视图类中写上authentication_classes = [ ],这是一个列表 需要实现 authenticate() ...

  2. Docker数据目录迁移解决方案

    场景 在docker的使用中随着下载镜像越来越多,构建镜像.运行容器越来越多, 数据目录必然会逐渐增大:当所有docker镜像.容器对磁盘的使用达到上限时,就需要对数据目录进行迁移. 如何避免: 1. ...

  3. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

  4. 在Ubuntu安装kubernetes

    一.安装Docker 1. 配置Docker docker安装完成后需要配置cgroup驱动为systemd来增强稳定性 sudo vim /etc/docker/daemon.json { &quo ...

  5. Tensorflow-卷积神经网络CNN

    卷积神经网络CNN 结构 池化操作 手写数字-卷积神经网络实现 import tensorflow as tf from tensorflow.examples.tutorials.mnist imp ...

  6. Oracle删除表中的重复数据

    Oracle数据库删除表中的重复数据,只保留其中的一条,以两个字段为例,提供两种方法 ①.直接delete重复的数据 delete from table_name t1 where (t1.col1, ...

  7. (一)Spring-Boot-操作-Redis

    Spring-Boot-操作-Redis 1.Spring Data Redis 1.1 引入依赖 1.2 配置 Redis 信息 1.3 使用 2.Spring Cache 2.1 引入依赖 2.2 ...

  8. Mycat安装并实现mysql读写分离,分库分表

    Mycat安装并实现mysql读写分离,分库分表 一.安装Mycat 1.1 创建文件夹 1.2 下载 二.mycat具体配置 2.1 server.xml 2.2 schema.xml 2.3 se ...

  9. 我用了半年的时间,把python学到了能出书的程度

    Python难学吗?不难,我边做项目边学,过了半年就通过了出版社编辑的面试,接到了一本Python选题,并成功出版. 有同学会说,你有编程基础外带项目实践机会,所以学得快.这话不假,我之前的基础确实加 ...

  10. Java基础进阶

    Java基础进阶J Object类 hashcode() toString() clone() getClass() notify() wait() equals() Random类 生成 随机数 U ...