简单计算题【离散化】【树状数组】

>Description
在这里插入图片描述


>Input
在这里插入图片描述

>Output
在这里插入图片描述
在这里插入图片描述


>Sample Input
4
1 4 3 2

>Sample Output
3


>解题思路

首先我们要知道一个树状数组与逆序对的东西(所以为了防爆,得用离散化把S序列离散一下在加进树状数组)

然后我们把符合(a,b)的方案数p,符合(c,d)的方案数q求出来(树状数组求逆序对,具体得理解树状数组太多了不想打了 ),ans=pq,
接着处理a≠b≠c≠d的情况,因为a已经小于b,c已经小于d,所以就只用在ans中减去a=c、a=d、b=c、b=d的情况,
预先求出lb[i],rb[i],ls[i],rs[i](分别为d为i时c的方案,a为i时b的方案,b为i时a的方案,c为i时d的方案)
四种情况(冒号后面a<b<c,分别考虑四种重叠情况下三个数的状态):

  1. a=c:s[a]>s[b],s[a]<s[c] 方案数为rb[i]*rs[i]
  2. a=d:s[a]>s[b]<s[c] 方案数为lb[i]*rb[i]
  3. b=c:s[a]<s[b]>s[c] 方案数为ls[i]*rs[i]
  4. b=d:s[a]>s[c],s[b]<s[c] 方案数为ls[i]*lb[i]

(自己推推就很容易理解了)

最后在加个longlong,不然只有20分


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;

struct ooo
{
	ll c, h;
} ss[100005];
ll n, t, s[100005], f[200005], p, q, ans;
ll lb[100005], rb[100005], ls[100005], rs[100005];

bool bmp (ooo aa, ooo bb) {return aa.c < bb.c;}
void add (ll x, ll y)
{
	for (; x <= n; x += x & (-x))
	  f[x] += y;
} //树状数组改值
ll ask (ll x)
{
	ll l = 0;
	for (; x; x -= x & (-x))
	  l += f[x];
	return l;
} //树状数组询问

int main()
{
	scanf ("%lld", &n);
	for (ll i = 1; i <= n; i++)
	  scanf ("%lld", &ss[i].c), ss[i].h = i;
	sort (ss + 1, ss + 1 + n, bmp);
	s[ss[1].h] = t = 1;
	for (ll i = 2; i <= n; i++)
	  if (ss[i].c != ss[i - 1].c) s[ss[i].h] = ++t;
	  else s[ss[i].h] = t; //离散化
	for (ll i = 1; i <= n; i++)
	{
		add (s[i], 1);
		ls[i] = ask (s[i] - 1);
		lb[i] = ask (n) - ask (s[i]);
		p += ls[i];
		q += lb[i];
	}
	ans = p * q;
	memset (f, 0, sizeof (f));
	for (ll i = n; i >= 1; i--)
	{
		add (s[i], 1);
		rs[i] = ask (s[i] - 1);
		rb[i] = ask (n) - ask (s[i]);
	}
	for (ll i = 1; i <= n; i++)
	  ans -= rs[i] * rb[i] + lb[i] * rb[i]
	       + ls[i] * rs[i] + lb[i] * ls[i]; 
	printf ("%lld", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值