• hdu 4455 Substrings(找规律&DP)


    Substrings

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1161    Accepted Submission(s): 351

    Problem Description
    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
     
    Input
    There 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,a 2…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 6
     
    Output
    For 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
     
    Source
     

    题意:

    给你一个数组{a1,a2,a3........an}。然后定义了一个询问。给你一个w。要你求出。所有a[i+1],a[i+2]......a[i+w]。中不同元素个数的和。i+w<=n。

    思路:

    dp[i]表示w为i时的答案。我们考虑dp[i+1]即长度增加一个后的情况。

    对于n=3时。dp[3]已知

    [1 1 2 ]3 4 4 5

    对于n=4时。

    [1 1 2 3] 4 4 5

    相当于在以前三元集中加入一个数。所以如果该元素出现过dp[4]的值和dp[3]值一样。

    如果不一样就要在dp[3]的基础上减一个。但是对于数组的最后三个数已经不能算作dp[4]的值。但dp[3]把它们

    算作在内。所以要把他们减出来。我们对于数组中的每一个数。维护一个数组pre[v]表示数值v上次出现的位置。那么i-pre[v]即两数的不重复区间长度。

    哎。。。比赛时居然为一个__int64卡了半天。还是不专业呀。都没有分析数据范围。。。还是最后十分钟做出来的。

    不然应该有机会做做其它题目的。

    详细见代码:

    #include <iostream>
    #include<string.h>
    #include<stdio.h>
    
    using namespace std;
    const int maxn=1000010;
    int a[maxn],pre[maxn],len[maxn];
    __int64 dp[maxn],rest;//注意数据范围呀!!
    bool vis[maxn];
    int main()
    {
        int n,q,w,i;
    
        while(scanf("%d",&n),n)
        {
            memset(pre,-1,sizeof pre);
            memset(len,0,sizeof len);
            memset(vis,0,sizeof vis);
            for(i=0;i<n;i++)
            {
                scanf("%d",a+i);
                len[i-pre[a[i]]]++;//统计各长度的数目
                pre[a[i]]=i;
            }
            for(i=n-1;i>=0;i--)
                len[i]+=len[i+1];//len[i]代表长度大于等于i的个数
            dp[0]=0;
            dp[1]=n;
            rest=1;
            vis[a[n-1]]=true;
            for(i=2;i<=n;i++)
            {
                dp[i]=dp[i-1]+len[i]-rest;//rest为长度不足i的部分
                if(!vis[a[n-i]])
                {
                    rest++;
                    vis[a[n-i]]=true;
                }
            }
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d",&w);
                printf("%I64d
    ",dp[w]);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    想当老板的人,三点特征很重要(转)
    突破三个自我,你就不光是老板的料
    掌握这3套创业战略 保你赚到百万财富 
    也感山西黑窑洞
    再游府河有感
    朋友的影响力非常大,朋友决定你的财富
    夏日乘凉
    职业生涯的八大“定位法则”
    一生何求
    赠你一方明月
  • 原文地址:https://www.cnblogs.com/riasky/p/3361019.html
Copyright © 2020-2023  润新知