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. luoguP2016 战略游戏

    题目描述 Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题.他要建立一个古城堡,城堡中的路形成一棵树.他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了 ...

  2. 在EXCEL中如何同时冻结行与列?

    鼠标所在的单元格的位置 ,决定了你冻结的行和列.如: 冻结第一行与第一列, 只需要将鼠标置于单元格在第二列,第二行. 点击冻结

  3. linux设备文件

    一.前言 在调用了alloc_chrdev_region函数或register_chrdev_region函数之后可以在/proc/devices中看到该设备的主设备号,比如我注册的hello模块的主 ...

  4. 并发编程常用工具类(一) countDownLatch和cyclicBarrier的使用对比

    1.CountDownLatch           countDownLatch的作用是让一组线程等待其他线程完成工作以后在执行,相当于加强版的join(不懂可以百度一下join的用法),一般在初始 ...

  5. Django Full Coverage

    Django(个人推荐, 如果项目较大 需要协同开发, 建议使用django这种重量级框架, 如果类似于纯api的后端应用建议使用 flask, 轻量小巧 , 麻雀虽小五脏俱全) 1.Django是什 ...

  6. jQuery 勾选启用输入框

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. 一个关于时区的bug

    起因: 在 Apollo 中配置了某活动的开始时间是 2020-05-15, 代码中的逻辑判断如下: const nowTime = new Date().getTime(); const start ...

  8. charles安装使用乱码连手机等问题解决方案

    捣鼓半天终于安装好了,给大家分享下我的过程 1.安装, 正常网上安装即可,我安装了个有汉化包的,,推荐链接 安装方法下载破解版,安装即可 安装包地址:https://pan.baidu.com/s/1 ...

  9. Web信息收集之搜索引擎-Zoomeye Hacking

    Web信息收集之搜索引擎-Zoomeye Hacking https://www.zoomeye.org ZoomEye(钟馗之眼)是一个面向网络空间的搜索引擎,"国产的Shodan&quo ...

  10. H3C交换机堆叠

    (1)      配置Device A# 将用作IRF物理端口的Ten-GigabitEthernet1/0/1-Ten-GigabitEthernet1/0/4的手工关闭.使用端口批量配置功能可以更 ...