三元组
三元组
给定 个两两不同的正整数 。
请你计算共有多少个三元组 能够同时满足:
输入格式
第一行包含整数 。
第二行包含 个整数 。
输出格式
一个整数,表示满足条件的三元组数量。
数据范围
前 个测试点满足 。
所有测试点满足 ,。
输入样例1:
3 3 2 1
输出样例1:
1
输入样例2:
3 2 3 1
输出样例2:
0
输入样例3:
4 10 8 3 1
输出样例3:
4
输入样例4:
4 1 5 4 3
输出样例4:
1
解题思路
先说一下当时比赛的思路,貌似有点复杂。当时想到的是先把问题规模缩小,只考虑两个数的情况。枚举每一个数,看看前面有多少个数大于当前的数,这个可以用树状数组来实现,对于第个数,前面()比大的数有个。
现在两个数的情况知道了,求三元组也是一样,枚举每一个数,然后看看前面有多少个数大于当前数,不过这里不再是加上比当前数要大的数的个数了,而是应该加上这些数所对应的,因为求的是三元组。也是用树状数组来实现,不过每次动态加的数不再是,而是。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 1e6 + 10; 7 8 int a[N]; 9 int cnt[N]; 10 LL tr[N]; 11 int xs[N], sz; 12 13 int lowbit(int x) { 14 return x & -x; 15 } 16 17 void add(int x, int c) { 18 for (int i = x; i <= sz; i += lowbit(i)) { 19 tr[i] += c; 20 } 21 } 22 23 LL query(LL x) { 24 LL ret = 0; 25 for (int i = x; i; i -= lowbit(i)) { 26 ret += tr[i]; 27 } 28 return ret; 29 } 30 31 int find(int x) { 32 int l = 1, r = sz; 33 while (l < r) { 34 int mid = l + r >> 1; 35 if (xs[mid] >= x) r = mid; 36 else l = mid + 1; 37 } 38 return l; 39 } 40 41 int main() { 42 int n; 43 scanf("%d", &n); 44 for (int i = 1; i <= n; i++) { 45 scanf("%d", a + i); 46 xs[++sz] = a[i]; 47 } 48 49 sort(xs + 1, xs + sz + 1); 50 // sz = unique(xs + 1, xs + sz + 1) - xs - 1; // 可以省去,因为题目保证每个数都不同 51 52 for (int i = 1; i <= n; i++) { 53 int t = find(a[i]); 54 cnt[i] += i - 1 - query(t); // 求大于a[i]的数的个数 55 add(t, 1); // 加1,这里求的是二元组 56 } 57 58 LL ret = 0, s = 0; 59 memset(tr, 0, sizeof(tr)); 60 for (int i = 1; i <= n; i++) { 61 int t = find(a[i]); 62 ret += s - query(t); // 求所有大于a[i]的数所对应cnt数组 63 s += cnt[i]; 64 add(t, cnt[i]); // 加cnt[i],这里求的是三元组 65 } 66 printf("%lld", ret); 67 68 return 0; 69 }
其实不用想得这么麻烦,我们可以枚举,这时就是看看左边有多少个满足,右边有多少个满足。分别用树状数组枚举两次,最后对于第个数左边比它大的个数,右边比它小的个数,那么对于第个数满足条件的三元组个数就是。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 1e6 + 10; 7 8 int a[N]; 9 int xs[N], sz; 10 int tr[N]; 11 int cnt[N]; 12 13 int find(int x) { 14 int l = 1, r = sz; 15 while (l < r) { 16 int mid = l + r >> 1; 17 if (xs[mid] >= x) r = mid; 18 else l = mid + 1; 19 } 20 return l; 21 } 22 23 int lowbit(int x) { 24 return x & -x; 25 } 26 27 void add(int x, int c) { 28 for (int i = x; i <= sz; i += lowbit(i)) { 29 tr[i] += c; 30 } 31 } 32 33 int query(int x) { 34 int ret = 0; 35 for (int i = x; i; i -= lowbit(i)) { 36 ret += tr[i]; 37 } 38 return ret; 39 } 40 41 int main() { 42 int n; 43 scanf("%d", &n); 44 for (int i = 1; i <= n; i++) { 45 scanf("%d", a + i); 46 xs[++sz] = a[i]; 47 } 48 49 sort(xs + 1, xs + sz + 1); 50 // sz = unique(xs + 1, xs + sz + 1) - xs - 1; // 可以省去,因为题目保证每个数都不同 51 52 for (int i = 1; i <= n; i++) { 53 int t = find(a[i]); 54 cnt[i] += i - 1 - query(t); 55 add(t, 1); 56 } 57 58 LL ret = 0; 59 memset(tr, 0, sizeof(tr)); 60 for (int i = n; i; i--) { 61 int t = find(a[i]); 62 ret += 1ll * cnt[i] * query(t - 1); 63 add(t, 1); 64 } 65 66 printf("%lld", ret); 67 68 return 0; 69 }
参考资料
AcWing 4709. 三元组(AcWing杯 - 周赛):https://www.acwing.com/video/4505/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16817970.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效