求助大佬看看哪里写挂了
查看原帖
求助大佬看看哪里写挂了
890233
gmx0424楼主2023/11/3 12:21
/*
P1637 三元上升子序列
题目:
	求i<j<k && ai<aj<ak个数
	
思路:
		
 三元上升子序列个数=每个数前面比它小的数的个数* 每个数后面比它大的数的个数之和
  
  所以维护i之前比i小的个数
  		  i之后比i大的个数
		
	1,离散化
	2.类似求逆序对,维护区间内出现的次数 
	 
*/
#include<bits/stdc++.h>
using namespace std;
int n;
const int maxn = 3e4 + 5;
int val[maxn << 2];
int big[maxn], small[maxn], a[maxn], b[maxn] ;


void pushup(int rt){
	val[rt] = val[rt<<1] +  val[rt<<1|1];
}


//void build(int rt, int l, int r){
//	if (l==r){
//		val[a[l]]++;
//		return;
//	}
//	int mid = (l+r) >> 1;
//	build(rt<<1,l,mid);
//	build(rt<<1|1,mid+1,r);
//	pushup(rt);
//}



void update(int rt, int l, int r, int x){
	if (l == r){
		val[x]++;
		return ;
	}
	int mid = (l+r)>>1;
	if(x <= mid){
		update(rt<<1,l,mid,x);
	}else{
		update(rt<<1|1,mid+1,r,x);
	}
	pushup(rt);
}



int query(int rt, int l, int r, int ql, int qr)
{

	if (ql <= l && r <= qr){
		return val[rt];
	}
	int mid = (l+r)>>1;
	int ans = 0;
	if(ql <= mid) ans += query(rt<<1,l,mid,ql,qr);
	if(qr > mid) ans += query(rt<<1|1,mid+1,r,ql,qr);
	return ans;
}


int main () {
	cin >> n;
	for (int i = 1; i <= n ;i++){
		cin >> a[i];
		b[i] = a[i];
	}
	
	sort(b+1,b+1+n);
	int m = unique(b+1,b+1+n) - b - 1;	//离散化 
	for (int i = 1; i <= n; i++){
		int id = lower_bound(b+1,b+1+m,a[i])-b;
		a[i] = id;
//		cout << a[i] << " ";
	}
	
//	build(1,1,n);
	
	for (int i = 1; i <= n; i++){
		if (a[i] - 1 > 0){
			small[i] = query(1,1,n,1,a[i]-1);
		}
		update(1,1,n,a[i]);
	}
	
	memset(val,0,sizeof(val));
	
	for (int i = 1; i <= n; i++){
		if (a[i] + 1 <= n){
			big[i] = query(1,1,n,a[i]+1,n);
		}
		update(1,1,n,a[i]);
	}
	
	int ans = 0;
	
	for (int i = 1; i <= n ;i++){
		ans += small[i] * big[i];
	}
	cout << ans;
	return 0;
} 
2023/11/3 12:21
加载中...