码迷,mamicode.com
首页 > 其他好文 > 详细

【HDOJ】4455 Substrings

时间:2015-11-12 23:38:17      阅读:444      评论:0      收藏:0      [点我收藏+]

标签:

5000ms的时限,还挺长的。算法是DP。
思路是找到ans[1..n]的结果,然后Query就容易做了。问题是怎么DP?
考虑:
1 1 2 3 4 4 5w=1: 7, 7 = 1 * 7
w=2: 10,10 = |{1,1}|+|{1,2}|+|{2,3}|+|{3,4}|+|{4,4}|+|{4,5}|=1+2+2+2+1+2=10
w=3: 12,  12 = |{1,1, 2}|+|{1,2, 3}|+|{2,3, 4}|+|{3,4, 5}|+|{4,4, 5}|
...
观察w=3如何在w=2的基础上求得,首先需要减去|{4,5}|,然后考虑2,3,4,5,5(每个集合的最后一个数)是否distinct。

因此,O(n^2)是可解得。不过n的范围是1e6,肯定超时。
那么,简化思路,分成三个部分。
1. ans[n-1];
2. 后k([1..n])个数中,distinct的数目可以在O(n)内求得。
3. 而考虑a[w..n]是否对数量增加1,可以换个思路考虑。
考虑1 1 2 3 4 4 5中的3,因为前面没有出现3,因此w=[1..4]时,这个3都会提供增量1。
考虑1 3 2 3* 4 4 5中的3*,因为前面有个3,两者间距2,因此w=[1..2]时,这个3会提供增量1。
可见弄个delta数组,两个O(n)循环可以确定针对w=[1..n]时,这个增量delta是多少。
最后合成一下就可以了。

  1 /* 4455 */
  2 #include <iostream>
  3 #include <string>
  4 #include <map>
  5 #include <queue>
  6 #include <set>
  7 #include <stack>
  8 #include <vector>
  9 #include <deque>
 10 #include <algorithm>
 11 #include <cstdio>
 12 #include <cmath>
 13 #include <ctime>
 14 #include <cstring>
 15 #include <climits>
 16 #include <cctype>
 17 #include <cassert>
 18 #include <functional>
 19 #include <iterator>
 20 #include <iomanip>
 21 using namespace std;
 22 //#pragma comment(linker,"/STACK:102400000,1024000")
 23 
 24 #define sti                set<int>
 25 #define stpii            set<pair<int, int> >
 26 #define mpii            map<int,int>
 27 #define vi                vector<int>
 28 #define pii                pair<int,int>
 29 #define vpii            vector<pair<int,int> >
 30 #define rep(i, a, n)     for (int i=a;i<n;++i)
 31 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 32 #define clr                clear
 33 #define pb                 push_back
 34 #define mp                 make_pair
 35 #define fir                first
 36 #define sec                second
 37 #define all(x)             (x).begin(),(x).end()
 38 #define SZ(x)             ((int)(x).size())
 39 #define lson            l, mid, rt<<1
 40 #define rson            mid+1, r, rt<<1|1
 41 
 42 const int maxn = 1e6+5;
 43 int a[maxn], b[maxn];
 44 int pre[maxn];
 45 __int64 delta[maxn], ans[maxn];
 46 bool mark[maxn];
 47 
 48 int main() {
 49     ios::sync_with_stdio(false);
 50     #ifndef ONLINE_JUDGE
 51         freopen("data.in", "r", stdin);
 52         freopen("data.out", "w", stdout);
 53     #endif
 54     
 55     int n, q, x;
 56     int l, tmp;
 57     int i, j, k;
 58     
 59     while (scanf("%d", &n)!=EOF && n) {
 60         for (i=1; i<=n; ++i) {
 61             scanf("%d", &a[i]);
 62             ++a[i];
 63         }
 64         memset(delta, 0, sizeof(delta));
 65         memset(pre, 0, sizeof(pre));
 66         memset(mark, 0, sizeof(mark));
 67         
 68         // handle last i number
 69         for (i=n,j=1; i>0; --i,++j) {
 70             if (mark[a[i]]) {
 71                 b[j] = b[j-1];
 72             } else {
 73                 b[j] = b[j-1]+1;
 74                 mark[a[i]] = true;
 75             }
 76         }
 77         // handle pre
 78         for (i=1; i<=n; ++i) {
 79             l = i - pre[a[i]];
 80             // [1, l]++
 81             delta[1]++;
 82             delta[l+1]--;
 83             pre[a[i]] = i;
 84         }
 85         ans[1] = n;
 86         for (i=2; i<=n; ++i) {
 87             delta[i] += delta[i-1];
 88             ans[i] = ans[i-1] + delta[i] - b[i-1];
 89         }
 90         
 91         scanf("%d", &q);
 92         while (q--) {
 93             scanf("%d", &x);
 94             printf("%I64d\n", ans[x]);
 95         }
 96     }
 97     
 98     #ifndef ONLINE_JUDGE
 99         printf("time = %d.\n", (int)clock());
100     #endif
101     
102     return 0;
103 }

 

【HDOJ】4455 Substrings

标签:

原文地址:http://www.cnblogs.com/bombe1013/p/4960435.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!