题目链接:http://icpc.moe/onlinejudge/showProblem.do?problemId=5520
动态规划之所以被称作玄学,是因为往往有时候很难去想到两个看起来不相干的东西之间的关系。
此题的题意是让我们求出所有连续子序列的所有不同元素的和。
我们用一个pre数组记录当前元素上一次出现的位置,dp记录取到当前位置时的总和,则状态转移方程为: dp[i] = dp[i-1] + (i - pre[a[i]])*a[i],这个状态转移方程应该不难理解,当再加一个元素的时候比起前一个元素增加的就是这个元素上一次出现的位置到当前位置的所有连续序列。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn = 1000000+5;
int pre[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
memset(pre,0,sizeof(pre));
LL dp = 0,sum = 0;
for(int i=1; i<=n; i++)
{
int a;
scanf("%d",&a);
dp += (i-pre[a])*a;
sum += dp;
pre[a] = i;
}
printf("%lld\n",sum);
}
}