LYK在研究一个有趣的东西。
假如有一个长度为n的序列,那么这个序列的权值将是所有有序二元组i,j的
Σaj−ai 其中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
alpq654321
(题目提供者)
题解:
对于一个区间l~r,我们可以发现第x个数贡献的次数为x*2-l-r((x-l)-(r-x)),然后我们用很恶心的瞎几把搞O(n)的处理判断下就行了。
PS:如果你对自己的常数足够自信,那你可以不用读入优化(反正我是要用的)
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,i,ans,p,a[1000001],bs[1000001],bn[1000001],rss[1000001],rsn[1000001],lss[1000001],lsn[1000001],sumsl[1000001],sumsr[1000001],sumnl[1000001],sumnr[1000001];
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main(){
scanf("%lld",&n);
for(i=1;i<=n;i++){
a[i]=read();
}
p=1024ll*1024*1024*4;
//printf("%lld\n",p);
for(i=1;i<=n;i++){
rss[i]+=bs[a[i]]+i*bn[a[i]];
rsn[i]=bn[a[i]];
bn[a[i]]++;bs[a[i]]+=i;
}
//printf("-1\n");
memset(bn,0,sizeof(bn));
memset(bs,0,sizeof(bs));
for(i=n;i;i--){
lss[i]+=bs[a[i]]+i*bn[a[i]];
lsn[i]=bn[a[i]];
bn[a[i]]++;bs[a[i]]+=i;
}
//printf("-2\n");
for(i=n;i;i--)sumsl[i]=sumsl[i+1]+rss[i];
for(i=n;i;i--)sumsr[i]=sumsr[i+1]+lss[i];
for(i=n;i;i--)sumnl[i]=sumnl[i+1]+rsn[i];
for(i=n;i;i--)sumnr[i]=sumnr[i+1]+lsn[i];
//printf("%lld\n",p);
for(i=1;i<=n;i++){
//printf("%lld %lld %lld %lld %lld %lld\n",i,sumnl[i],sumnr[i+1],sumsl[i],sumsr[i+1],a[i],p);
ans=(ans+((((sumnl[i]-sumnr[i+1])*2*i-sumsl[i]+sumsr[i+1]))*a[i])%p)%p;
}
printf("%lld",ans);
}