PAT (Top Level) Practice 1009 Triple Inversions (35)

逆序对问题的升级版本(不知道的童鞋自行百度BIT/线段树求逆序对)
本体思路以三个数中间的数为基准,找前面比他大得数有几个
后面比他小的数有几个(可以算出来)
然后相乘+到res里即可

#include <bits/stdc++.h>
using namespace std;
#define N (int)1e5+10
int arr[N];
#define lc root<<1
#define rc root<<1|1
typedef long long ll; 
struct seg{
	int l, r;
	ll he, lazy, tag;
}t[4*N];
void build(int root, int l, int r)
{
	t[root].l = l, t[root].r = r;
	t[root].lazy = 0;
	t[root].tag = -1;
	if (l == r)
	{
		t[root].he = 0;
		return;
	}
	int m = (l + r) >> 1;
	build(lc, l, m);
	build(rc, m+1, r);
	t[root].he = t[lc].he + t[rc].he;
}
void imptag(int root, ll change)
{
	t[root].tag = change;
	t[root].he = (t[root].r - t[root].l + 1) * change;
	t[root].lazy = 0;
}
void implazy(int root, ll change)
{
	t[root].lazy += change;
	t[root].he += (t[root].r - t[root].l + 1) * change;
}
void pushdown(int root)
{
	ll temp1 = t[root].tag;
	if (temp1 != -1)
	{
		imptag(lc, temp1);
		imptag(rc, temp1);
		t[root].tag = -1;
	}
	ll temp2 = t[root].lazy;
	if (temp2)
	{
		implazy(lc, temp2);
		implazy(rc, temp2);
		t[root].lazy = 0;
	}
}
void assignment(int root, int l, int r, ll change)
{
	if (r < t[root].l || l > t[root].r) return;
	if (l <= t[root].l && t[root].r <= r)
	{
		imptag(root, change);
		return;
	}
	pushdown(root);
	assignment(rc, l, r, change);
	assignment(lc, l, r, change);
	t[root].he = t[lc].he + t[rc].he;
}
void update(int root, int l, int r, ll change)
{
	if (r < t[root].l || l > t[root].r) return;
	if (l <= t[root].l && t[root].r <= r)
	{
		implazy(root, change);
		return;
	}
	pushdown(root);
	update(rc, l, r, change);
	update(lc, l, r, change);
	t[root].he = t[lc].he + t[rc].he;
}
ll query(int root, int l, int r)
{
	if (r < t[root].l || l > t[root].r) return 0;
	if (l <= t[root].l && t[root].r <= r)
	{
		return t[root].he;
	}
	pushdown(root);
	return query(rc, l, r) + query(lc, l, r);
}

int main(void)
{
	int n;
	ll res = 0; int i;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
		scanf("%d", &arr[i]);
	}
	build(1, 1, n);
	update(1, arr[1], arr[1], 1);
	for (i = 2; i <= n; i++)
	{
		ll temp1 = query(1, arr[i]+1, n);
		ll temp2 = arr[i]-1 - (i-1-temp1);
		res += temp1 * temp2;
		update(1, arr[i], arr[i], 1);
	}
	cout << res;
}

线段树部分为带lazy和tag的模板,大家可以复制一下用。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值