HDU 4455 Substrings 第37屆ACM/ICPC 杭州賽區現場賽 C題 (DP)

來源:互聯網
上載者:User
Substrings

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

Problem DescriptionXXX 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 a1,a2…an, 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<=106, 0<=Q<=104, 0<= a1,a2…an <=106 

 

OutputFor 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 Input7 1 1 2 3 4 4 5 3 1 2 3 0 

 

Sample Output7 10 12 

 

Source2012 Asia Hangzhou Regional Contest   這題不容易想到,一看題目,看到這資料範圍,看到查詢的方式。。。一直在往樹狀數組或者線段樹方面去想。想到了用DP解決就不難了。用DP的思路O(n)複雜度解決。以範例為例說明:1 1 2 3 4 4 5;明顯dp[1]=n=7;長度為1的時候有7個區間。從長度為1到長度為2,就是把前6個區間往後增加一個數,把最後一個區間去掉。增加的6個數要看在該區間是否出現過,只要看它上一個相等的元素距離是否大於2所以dp[2]=dp[1]-1+4; 以此類推就可以得出所以的dp值了。dp[i]=dp[i-1]-A+B;減的A是最後一個長度為i-1的區間的不同數的個數,這個很容易預先處理得出來。加的B是第t個數到它上一個數的距離大於i-1的個數.這個B值也容易得出。用s[i]表示離上一個數的距離為i的個數,不斷減掉就得到B了。 具體看代碼:
//============================================================================// Name        : HDU4455.cpp// Author      : kuangbin// Version     :// Copyright   : Your copyright notice// Description :// DP////============================================================================#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>using namespace std;const int MAXN=1000010;int a[MAXN];//1-n輸入的數列int f[MAXN];//f[i]表示a[i]在前面最近出現的位置,f[i]==0表示從左至右第一次出現int s[MAXN];//s[i]表示 t-f[t]==i,1<=t<=n的t的個數,即離上一個相等元素的距離為i的個數long long dp[MAXN];//需要輸出的結果int ss[MAXN];//ss[i]表示最後的i個數含有的不同元素的個數int main(){    int n;    int m;    while(scanf("%d",&n)==1 && n)    {        memset(f,0,sizeof(f));        memset(s,0,sizeof(s));        //順著求s數組        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            s[i-f[a[i]]]++;            f[a[i]]=i;        }        memset(f,0,sizeof(f));//f數組標記在後面是否出現過        ss[1]=1;        f[a[n]]=1;        for(int i=2;i<=n;i++)        {            if(f[a[n-i+1]]==0)            {                f[a[n-i+1]]=1;                ss[i]=ss[i-1]+1;            }            else ss[i]=ss[i-1];        }        dp[1]=n;        int sum=n;        //從dp[i-1]擴充到dp[i]就是去掉最後一個區間的個數,把前面的區間長度增加1,        //加上相應增加的種類數        for(int i=2;i<=n;i++)        {            dp[i]=dp[i-1]-ss[i-1];//減掉最後一個區間的種類數            sum-=s[i-1];            dp[i]+=sum;//加上前面的區間增加一個長度後增加的種類數        }        scanf("%d",&m);        int t;        while(m--)        {            scanf("%d",&t);            printf("%I64d\n",dp[t]);        }    }    return 0;}

 

  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.