题意:对于i上一个同颜色的位置j,ans+=(j+1~i-1的颜色种类)
做法:考场时傻逼了没想到,题做得少。枚举R,统计区间和。由于同种颜色数量不影响贡献R有顺序只用考虑L,每次颜色重复就把原位置-1,当前位置+1。
#include<bits/stdc++.h>
#define inf 1000000007
#define mid ((l+r)/2)
#define l(i) ((int)i.length())
using namespace std;
int n,m,a[200005],bz[200005],tr[20000005];
long long ans;
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<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
long long query(int l,int r,int k,int x,int y)
{
if(x>y)return 0;
if(l==x&&r==y)
{
return tr[k];
}
if(y<=mid)
{
return query(l,mid,k*2,x,y);
}
if(x>mid)
{
return query(mid+1,r,k*2+1,x,y);
}
return query(l,mid,k*2,x,mid)+query(mid+1,r,k*2+1,mid+1,y);
}
void ins(int l,int r,int k,int x,int y)
{
if(l==r)
{
tr[k]+=y;
return;
}
if(x<=mid)ins(l,mid,k*2,x,y);
else ins(mid+1,r,k*2+1,x,y);
tr[k]=tr[k*2]+tr[k*2+1];
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
ans+=query(1,n,1,bz[a[i]]+1,i-1);
ins(1,n,1,i,1);
if(bz[a[i]])ins(1,n,1,bz[a[i]],-1);
bz[a[i]]=i;
}
printf("%lld\n",ans);
return 0;
}