洛谷 P1637 三元上升子序列
题目描述
Erwin最近对一种叫"thair"的东西巨感兴趣。。。
在含有n个整数的序列a1,a2......an中,
三个数被称作"thair"当且仅当i<j<k且ai<aj<ak
求一个序列中"thair"的个数。
输入格式
开始一个正整数n,
以后n个数a1~an。
输出格式
"thair"的个数
输入输出样例
输入 #1
4 2 1 3 4
输出 #1
2
输入 #2
5 1 2 2 3 4
输出 #2
7
说明/提示
对样例2的说明:
7个"thair"分别是
1 2 3 1 2 4 1 2 3 1 2 4 1 3 4 2 3 4 2 3 4 约定 30%的数据n<=100
60%的数据n<=2000
100%的数据n<=30000
大数据随机生成
0<=a[i]<=maxlongint
思路:我做完这题后,竟然发现没大有和我做法一样的。。。。还是简要说明一下吧。。。其实这个题和求正序对很相似,只不过需要稍微修改一下而已,维护两棵树状数组,第一棵维护的就是求正序对时的每个数的出现次数,第二棵维护以该数为结尾的正序对的个数,我们不难看出,以一个数为结尾的三元上升序列的个数就等于在该数前面的所有比该数小的数为结尾的正序对个数的总和,我们依据这个条件,和正序对求和类似的方法求出答案即可。
PS:其实我的做法好像是树套树???
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N = 3e4 + 5; 7 typedef long long ll; 8 ll read() 9 { 10 ll ret = 0; 11 char ch = getchar(); 12 while(ch < '0' || ch > '9') ch = getchar(); 13 while(ch >= '0' && ch <= '9') 14 {ret = ret * 10 + ch - '0'; ch = getchar();} 15 return ret; 16 } 17 int n; 18 #define lowbit(x) x & -x; 19 ll atr[N][2]; 20 void modify_add(int pos, ll v, int id) 21 { 22 while(pos <= n) 23 { 24 atr[pos][id] += v; 25 pos += lowbit(pos); 26 } 27 } 28 ll ask_presum(int pos, int id) 29 { 30 ll ret = 0; 31 while(pos) 32 { 33 ret += atr[pos][id]; 34 pos -= lowbit(pos); 35 } 36 return ret; 37 } 38 ll f[N], lsh[N]; 39 int main() 40 { 41 scanf("%d", &n); 42 for(int i = 1; i <= n; i ++) f[i] = read(), lsh[i] = f[i]; 43 sort(lsh + 1, lsh + 1 + n); 44 int sup = unique(lsh + 1, lsh + 1 + n) - (lsh + 1); 45 ll ans = 0; 46 for(int i = 1; i <= n; i ++) 47 { 48 int pos = lower_bound(lsh + 1, lsh + 1 + sup, f[i]) - lsh; 49 modify_add(pos, 1, 0); 50 modify_add(pos, ask_presum(pos - 1, 0), 1); 51 ans += ask_presum(pos - 1, 1); 52 } 53 printf("%lld\n", ans); 54 return 0; 55 }