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 }
时间: 2024-11-17 02:51:34