对于某个数
如果左边区间是[l,i]
右边区间是[i,r]
正常是 两个区间长度相乘,但是这个题目会重复
所以问题转化成一个二维坐标
x轴是L,y轴是R
那么就变成一个矩阵,左下角是(l,i)右上角是(i,r)
对于矩阵每个点都是合法的,所以变成扫描线求不重复的点对
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using Node=tuple<int,int,int>;
const long long inf=1e18;
int n;
int a[N];
int l[N],r[N];
struct segment{
int x,y1,y2;
int d;
bool operator<(const segment&t) const{
return x<t.x;
}
}seg[N*10];
struct node{
int l,r;
int cnt,len;
}tr[N*10];
void pushup(int u)
{
if(tr[u].cnt)
{
tr[u].len=tr[u].r-tr[u].l+1;
}
else if(tr[u].cnt==0&&tr[u].l!=tr[u].r)
{
tr[u].len=tr[u<<1].len+tr[u<<1|1].len;
}
else
{
tr[u].len=0;
}
}
void build(int u,int l,int r){
tr[u]={l,r,0,0};
if(l==r) return ;
else{
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
}
}
void modify(int u,int l,int r,int d)
{
if(tr[u].l>=l&&tr[u].r<=r){
tr[u].cnt+=d;
pushup(u);
}else{
int mid=tr[u].r+tr[u].l>>1;
if(l<=mid) modify(u<<1,l,r,d);
if(r>mid) modify(u<<1|1,l,r,d);
pushup(u);
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
unordered_map<int,int> mp;
for(int i=1;i<=n;i++){
if(mp.count(a[i])) l[i]=mp[a[i]]+1;
else l[i]=1;
mp[a[i]]=i;
}
mp.clear();
for(int i=n;i>=1;i--){
if(mp.count(a[i])) r[i]=mp[a[i]]-1;
else r[i]=n;
mp[a[i]]=i;
}
int j=0;
int res=0;
map<int,vector<Node>> g;
for(int i=1;i<=n;i++)
{
int x1=l[i],y1=i,x2=i,y2=r[i];
g[x1].emplace_back(y1,y2,1);
g[x2+1].emplace_back(y1,y2,-1);
}
sort(seg,seg+j);
int m=200000;
build(1,1,m);
int lst=-1;
for(auto [k,v]:g)
{ if(lst!=-1) res+=tr[1].len*(k-lst);
for(auto [y1,y2,d]:v)
{
modify(1,y1,y2,d);
}
// cout<<k<<" "<<tr[1].len<<"\n";
lst=k;
}
cout<<res;
}
//1 2 3 4
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}