正题
题目链接:https://www.luogu.com.cn/problem/P6477
话说这是luogu的冥间数据
题目大意
nnn个数的序列,f(l,r)f(l,r)f(l,r)表示l∼rl\sim rl∼r有多少个不同的数字。
求∑l=1n∑r=ln(f(l,r))2\sum_{l=1}^n\sum_{r=l}^n(f(l,r))^2l=1∑nr=l∑n(f(l,r))2
解题思路
考虑多一个数字会多出2n+12n+12n+1(n表示原来数字个数)。
线段树维护f(1∼i−1,i)f(1\sim i-1,i)f(1∼i−1,i)的和,然后每个数字能影响的范围是i到上一个和它相同的数字的后一个位置处,我们修改这部分的数据然后每次统计答案即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lowbit(x) (x&-x)
#define siz(x) (t[x].r-t[x].l+1)
#define k(x) (((x)>XJQ)?((x)-XJQ):(x))
#define ll long long
using namespace std;
const ll N=1e6+10,XJQ=1e9+7;
ll n,ans,answer;
ll a[N],b[N],last[N],v[N];
ll read() {ll x=0,f=1; char c=getchar();while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();return x*f;
}
struct Seq_Tree{struct Tree_node{ll l,r,val,lazy;}t[N*4];void Build(ll x,ll l,ll r){t[x].l=l;t[x].r=r;if(l==r)return;ll mid=(l+r)>>1;Build(x*2,l,mid);Build(x*2+1,mid+1,r);return;}void DownData(ll x){if(!t[x].lazy)return;(t[x*2].lazy+=t[x].lazy)%=XJQ;(t[x*2+1].lazy+=t[x].lazy)%=XJQ;(t[x*2].val+=t[x].lazy*siz(x*2))%=XJQ;(t[x*2+1].val+=t[x].lazy*siz(x*2+1))%=XJQ;t[x].lazy=0;return;}void Change(ll x,ll l,ll r,ll val){if(t[x].l==l&&t[x].r==r){(t[x].lazy+=val)%=XJQ;(t[x].val+=val*siz(x))%=XJQ;return;}DownData(x);ll mid=(t[x].l+t[x].r)>>1;if(r<=mid) Change(x*2,l,r,val);else if(l>mid) Change(x*2+1,l,r,val);else Change(x*2,l,mid,val),Change(x*2+1,mid+1,r,val);t[x].val=(t[x*2].val+t[x*2+1].val)%XJQ;return;}ll Ask(ll x,ll l,ll r){if(t[x].l==l&&t[x].r==r)return t[x].val;DownData(x);ll mid=(t[x].l+t[x].r)>>1;if(r<=mid) return Ask(x*2,l,r);if(l>mid) return Ask(x*2+1,l,r);return (Ask(x*2,l,mid)+Ask(x*2+1,mid+1,r))%XJQ;}
}T;
int main()
{n=read();for(ll i=1;i<=n;i++)a[i]=b[i]=read();sort(b+1,b+1+n);ll m=unique(b+1,b+1+n)-b-1;for(ll i=1;i<=n;i++){a[i]=lower_bound(b+1,b+1+m,a[i])-b;last[i]=v[a[i]];v[a[i]]=i;}T.Build(1,1,n);T.Change(1,1,1,1);ans=answer=1;for(ll i=2;i<=n;i++){(ans+=2*T.Ask(1,last[i]+1,i)+i-last[i])%=XJQ;T.Change(1,last[i]+1,i,1);(answer+=ans)%=XJQ;}printf("%lld",answer);
}