正题
题目链接:https://www.luogu.com.cn/problem/P6477
话说这是luogu的冥间数据
题目大意
个数的序列, 表示 有多少个不同的数字。
求
解题思路
考虑多一个数字会多出 (n表示原来数字个数)。
线段树维护 的和,然后每个数字能影响的范围是i到上一个和它相同的数字的后一个位置处,我们修改这部分的数据然后每次统计答案即可。
#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);
}