【51nod】区间求和

LYK在研究一个有趣的东西。

假如有一个长度为n的序列,那么这个序列的权值将是所有有序二元组i,j的 Σajai 其中1<=i<j<=n。
但是这个问题似乎太简单了。
于是LYK想在所有有序二元组k,l中若ak=al其中1<=k<l<=n,则将 a{k},a{k+1},...,a{l}  提出当做一个序列,计算它的权值。
并统计所有这样的区间的权值和。
由于答案可能很大,你只需要将答案对2^32取模即可。
建议使用读入优化。
Input
第一行一个整数n(1<=n<=1000000),接下来一行n个数ai(1<=ai<=1000000)表示LYK的序列。
Output
一行表示答案。
Input示例
5
3 4 5 5 3
Output示例
2

题解:每次取出一个区间[l, r],发现a[i] 产生的贡献为 2*i-l-r. 预处理一下prenum[], presum[], prenum[i]表示[1, i]有多少个和a[i]相同, presum[i]表示[1, i]与a[i]相同的数所在的下标和,同理预处理出nexnum[], nexsum[].O(n)扫一遍维护一下l, r, 2*i即可递推出各个值。

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <string.h>
 5 
 6 using namespace std;
 7 #define ll unsigned long long
 8 const int N = 1e6+5;
 9 int n, a[N];
10 int pre[N], nex[N], pos[N];
11 int prenum[N], nexnum[N];
12 int presum[N], nexsum[N];
13 int fl[N], fr[N], f[N];
14 
15 int main(){
16     scanf("%d", &n);
17     for(int i = 1; i <= n; i++) scanf("%d", a+i);
18 
19     memset(pos, 0, sizeof(pos));
20     for(int i = 1; i <= n; i++){
21         pre[i] = pos[ a[i] ];
22         prenum[i] = prenum[ pre[i] ]+1;//前面的个数
23         presum[i] = presum[ pre[i] ]+i;//前面的下标和
24         pos[ a[i] ] = i;
25     }
26     memset(pos, 0, sizeof(pos));
27     for(int i = n; i; i--){
28         nex[i] = pos[ a[i] ];
29         nexnum[i] = nexnum[ nex[i] ]+1;
30         nexsum[i] = nexsum[ nex[i] ]+i;
31         pos[ a[i] ] = i;
32     }
33 
34     for(int i = 1; i <= n; i++){
35         fl[i] = fl[i-1];
36         fl[i] += i*nexnum[i];
37         fl[i] -= presum[i-1];
38     }
39     for(int i = n; i; i--){
40         fr[i] = fr[i+1];
41         fr[i] += i*prenum[i];
42         fr[i] -= nexsum[i+1];
43     }
44 
45     for(int i = 1; i <= n; i++)
46         f[i] = f[i-1]+nexnum[i]-prenum[i-1];
47     unsigned int ans = 0;
48     for(int i = 1; i <= n; i++){
49         //printf("i %d: %d %d %d\n", i, fl[i], fr[i], f[i]);
50         ans += a[i]*(2*i*f[i]-fl[i]-fr[i]);
51     }
52     printf("%u\n", ans);
53     return 0;
54 }
View Code

 

posted @ 2016-11-28 20:39  我在地狱  阅读(592)  评论(0编辑  收藏  举报