题意:对于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; }