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

二次信任 提交于 2019-12-02 11:39:34

逆序对问题的升级版本(不知道的童鞋自行百度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的模板,大家可以复制一下用。。。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!