ZOJ-3872-Beauty of Array-思维
ZOJ-3872-Beauty of Array
传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3872
参考:https://blog.csdn.net/u013050857/article/details/45285515
题意:
定义Beauty数是一个序列里所有不相同的数的和,求一个序列所有子序列的Beauty和
1 <= N <= 100000
【解题思路】
由于数据比较大,常规方法求子序列和肯定是行不通的,我们不妨这样想:
因为要区别不同的数,可以看成序列里的数是一个一个加进去的,每次加入一个数,统计前面序列里第一次出现新加入的这个数的序列的dp(就是找到前面最近的相同数,从这个位子后面开始计算),
注意到每次多的x,一定是在所在序列独一无二的,不然相当于没有加上,考虑完独一无二,再考虑重复的,只用加上前一项的dp即可。
举个例子:
1 2 3 1
定义dp(当前元素前面(包括自己)所有包含自己的子序列的和)
定义sum(当前元素前面所有子序列的和,包括此元素)
//输入 1 2 3 1
//dp 1 5 14 14+3
//sum 1 6 20 37
//a[i] 1 2 3
理解了思路,代码很容易实现,也是比较短,精髓都在for循环里,因为只用了一个for循环,每次新加入一个元素,就可以求出当前所有子序列的Beauty和,所以复杂度为O(n).
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 100009; int a[maxn]; int main(){ int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); memset(a,0,sizeof(a)); long long dp=0,sum=0; for(int i=1;i<=n;i++) { int x; scanf("%d",&x); dp+=(i-a[x])*x; sum+=dp; a[x]=i; } printf("%lld\n",sum); } return 0; }
skr