#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const int maxn = 1000007;
int n, q, a[maxn], sub[maxn], cnt[maxn], add[maxn], l[maxn];
LL dp[maxn];
bool vis[maxn];
void init() {
sub[n+1] = 0; cnt[0] = 0;
memset(vis, false, sizeof(vis));
memset(add, 0, sizeof(add));
memset(l, 0, sizeof(l));
for(int i = n; i > 0; --i) {
if(!vis[a[i]]) sub[i] = sub[i+1]+1, vis[a[i]] = true;
else sub[i] = sub[i+1];
}//sub表示从i开始出现的数字的个数
for(int i = 1; i <= n; ++i) {
if(l[a[i]]) add[i-l[a[i]]]++, cnt[i] = cnt[i-1]+1;
else cnt[i] = cnt[i-1];
l[a[i]] = i; //l数组表示a[i]上次出现的位置
}//cnt数组表示当前位置之前出现的相同元素的个数
dp[1] = n;
for(int i = 1; i <= n; ++i) add[i] += add[i-1];
//add[len]数组表示ai = aj且j-i <= len + 1的数对个数
for(int i = 2; i <= n; ++i)
dp[i] = dp[i-1] + (n-i+1 - add[i-1]) - sub[n-i+2] + cnt[i-1];
}
int main() {
while(~scanf("%d", &n) && n) {
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
init();
scanf("%d", &q);
while(q--) {
int tmp; scanf("%d", &tmp);
printf("%lld\n", dp[tmp]);
}
}
}
HDU 4455 Substrings
最新推荐文章于 2023-08-15 02:27:02 发布
本文介绍了一种使用C++实现的高效算法,该算法通过预处理数组和动态规划技术来加速查询过程。文章详细解释了如何初始化关键数据结构,如sub数组记录不同位置的唯一元素数量,cnt数组追踪重复元素,以及dp数组存储中间结果用于快速求解。
880

被折叠的 条评论
为什么被折叠?



