JZOJ 1341. 失眠 题解
题目大意#
给出一个长度为\(n\)的排列,求其中满足i<j<k且a[i]<a[k]且a[k]<a[j]的三元组(i,j,k)个数.
\(n\leq 100000\)
思路#
设满足i<j<k且a[i]<a[k]且a[k]<a[j]的三元组(i,j,k)个数为a.
满足i<j<k且a[i]<a[j]且a[j]<a[k]的三元组(i,j,k)个数为b.
满足i<j<k且a[i]<a[j]且a[i]<a[k]的三元组(i,j,k)个数为c.
显然有c=a+b
c,b都可以用树状数组轻松求出,相减就得到题目要求的a了。
Code#
#include <cstdio>
#include <cstring>
#include <cstdlib>
typedef long long ll;
const int N = 2e5 + 7;
ll ans = 0, c[N], r[N];
int n, a[N];
void add(int po)
{ for (; po <= n; po += (po & (-po))) c[po]++; }
ll sum(int po)
{
ll ret = 0;
for (; po; po -= (po & (-po))) ret += c[po];
return ret;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", a + i);
for (int i = n; i >= 1; i--)
{
r[i] = sum(n) - sum(a[i]);
ans += r[i] * (r[i] - 1) / 2, add(a[i]);
}
memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++)
ans -= sum(a[i] - 1) * r[i], add(a[i]);
printf("%lld\n", ans);
return 0;
}
作者:zjlcnblogs
出处:https://www.cnblogs.com/zjlcnblogs/p/10795697.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步