標籤:dp 找規律
1.題目描述:點擊開啟連結
2.解題思路:本題利用dp解決。不過這個dp的思路的確比太容易想到。需要觀察規律才能發現。我們可以從貢獻值的角度考慮。以題目中給的範例來說明這種方法。
通過觀察相鄰兩個w值,我們會發現一個事實:每個大區間都包含了小區間的解(這裡的解即原題中的sum值)。但是這還不夠,觀察圖上標記為紅色的數字,它們可以看做是上一個w值對應的區間多出來的新數字,如果我們可以算出這些紅色數位貢獻值,那麼我們就能得到當前w下的解。那麼該如何計算呢?
繼續觀察後會發現,每次w增加1,區間個數就會減少1個,也就是說,w-1時候的最後一個區間的結果要被減掉,才是w-1的解對當前w的貢獻。接下來看紅色數位貢獻,由於當前區間長度為w,那麼某個數字i和前一個i的距離差<w時,這些數字都不能算入。比如以w=5的情況為例,w=5時候,第一個紅色數字4要被算入,因為它和前一個4(如果不存在前一個數就看做在0位置,數組的起始下標從1開始)距離為5,不滿足距離<w,因此要被算入,而第二個紅色數字4和前一個4距離為1,滿足1<w的要求,因此不能被算入。也就是說,我們需要知道數位距離分別有幾個,比如距離為x的有dis[x]個,那麼w-1時候的紅色數位貢獻值假設為sum,那麼w時候,紅色數位貢獻就是sum-dis[w-1]。同時,我們用last[i]表示最後i個數字有幾種不同的數字。於是得到如下的遞推式:
dp(w)=dp(w-1)-last(w-1)+(sum-dis[w-1]);
上式中的sum是w-1時候紅色數字對答案的貢獻。當w=0時候,sum=n。這樣就可以用O(1)時間得到所有的dp(w)了。當然,根據上述分析,我們需要提前預先處理出來dis[i]和last[i],詳細過程見代碼。
本題最終的時間複雜度是O(N+Q)。
3.代碼:
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int N = 1000010;int a[N], dis[N], vis[N], last[N], sum;ll dp[N];int n;int main(){while (~scanf("%d", &n) && n){sum = n; //sum是前一個w值中紅色數字對答案的貢獻值me(vis); me(dis);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);dis[i - vis[a[i]]]++; //統計不同距離的個數vis[a[i]] = i;//更新a[i]上一次出現的位置}me(vis);last[1] = 1;//last[i]表示最後i個數中有幾個不同的數vis[a[n]] = 1;//標記a[n]訪問過for (int i = 2; i <= n; i++)if (!vis[a[n - i + 1]])//發現新的沒有出現過的數,last[i]++{vis[a[n - i + 1]]++;last[i] = last[i - 1] + 1;}else last[i] = last[i - 1];dp[1] = n;for (int i = 2; i <= n; i++){sum -= dis[i - 1];//更新sum,得到當前w時候紅色數字對答案的貢獻值dp[i] = dp[i - 1] - last[i - 1] + sum; }int q;scanf("%d", &q);for (int i = 0; i<q; i++){int w;scanf("%d", &w);printf("%I64d\n", dp[w]);}}}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
HDU 4455 Substrings (2012年杭州賽區現場賽C題)