主席树做法,特判了 1 ,把所有连续的 1 都放到一起了,证明可得只有 1 才会出现重复情况,但是 45昏,甚至有个点TLE
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,cnt,m,ans;
int a[N],l[N],r[N],root[N],b[N],num[N];
stack<pair<int,int> > s;
struct node{
int sum,ls,rs;
}tree[N<<5];
void update(int pre,int &now,int l,int r,int p,int v){
now=++cnt;
tree[now]=tree[pre];
if(l==r) return tree[now].sum+=v,void();
int mid=(l+r)>>1;
if(p<=mid) update(tree[pre].ls,tree[now].ls,l,mid,p,v);
else update(tree[pre].rs,tree[now].rs,mid+1,r,p,v);
tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum;
return ;
}
int query(int L,int R,int l,int r,int ql,int qr){
if(ql<=l && qr>=r) return tree[R].sum-tree[L].sum;
int mid=(l+r)>>1,res=0;
if(ql<=mid) res+=query(tree[L].ls,tree[R].ls,l,mid,ql,qr);
if(qr>mid) res+=query(tree[L].rs,tree[R].rs,mid+1,r,ql,qr);
return res;
}
signed main(){
scanf("%lld",&n);
int N=1e9+10;
for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
int c=0;
for(int i=1;i<=n;i++){
c++;
if(b[i]!=b[i+1] || b[i]!=1){
if(b[i]==1) ans+=(c+1)*c/2;
a[++m]=b[i],num[m]=c,c=0;
}
}
for(int i=1;i<=m;i++) update(root[i-1],root[i],1,N,a[i],num[i]);
for(int i=1;i<=m;i++){
while(s.size() && s.top().first<=a[i]) s.pop();
if(s.size()) l[i]=s.top().second;
l[i]++;
s.push(make_pair(a[i],i));
}
while(s.size()) s.pop();
s.push(make_pair(2e18+10,m+1));
for(int i=m;i>=1;i--){
while(s.size() && s.top().first<=a[i]) s.pop();
if(s.size()) r[i]=s.top().second;
r[i]--;
s.push(make_pair(a[i],i));
}
for(int i=1;i<=m;i++){
int llen=i-l[i]+1,rlen=r[i]-i+1;
if(a[i]==1) continue ;
if(llen<rlen){
for(int j=l[i];j<=i;j++){
int x=a[i]/a[j];
ans+=num[j]*query(root[i-1],root[r[i]],1,N,1,x);
}
}else{
for(int j=i;j<=r[i];j++){
int x=a[i]/a[j];
ans+=num[j]*query(root[l[i]-1],root[i],1,N,1,x);
}
}
}
printf("%d",ans);
return 0;
}