三元上升子序列
题目链接:https://www.luogu.com.cn/problem/P1637
题意:
给定数组,求i<j<k且a[i]<a[j]<a[k]的三元组数量
思路:
不妨枚举a[j]
这样我们只需要知道 它前面的数中 有多少个小于它的
它后面的数 有多少个大于它的
可以通过两个树状数组维护
将树状数组数组视为桶(因此边界为max(a[i])
每次可以快速查询大小在[1,a[i]]范围内的 数的数量。
已知已经枚举的数的数量
求出局部答案然后累加即可
思想和树状数组求逆序对完全一致
int s[maxn];
int t[maxn];
int n;
int lowerbit(int x){
return x&-x;
}
void add(int p,int x,int opt){
while(p<=1e5){
if(opt==1)s[p]+=x;else t[p]+=x;
p+=lowerbit(p);
}
}
int query(int p,int opt){
int res=0;
while(p){
if(opt==1)res+=s[p];else res+=t[p];
p-=lowerbit(p);
}
return res;
}
void solve(){
cin>>n;
vector<int>a(n+1);
rep(i,1,n)cin>>a[i];
rep(i,1,n){
add(a[i],1,1);
}
int ans=0;
rep(i,1,n){
int num=i-1;
int equal=query(a[i],2)-query(a[i]-1,2);
int les=query(a[i],2)-equal;
int big=num-query(a[i],2);//[1,i-1]所有大于a[i]的数的数量
int total_big=n-query(a[i],1);//[1,n]所有大于a[i]的数的数量
int dif=total_big-big;//[i+1,n]所有大于a[i]的数的数量
ans+=les*1*dif;
add(a[i],1,2);
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号