三元逆序对 求i<j<k && a[i]>a[j]>a[k] 的对数 树状数组Codeforces 61E Enemy is weak

http://codeforces.com/problemset/problem/61/E

E. Enemy is weak

time limit per test

5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The Romans have attacked again. This time they are much more than the Persians but Shapur is ready to defeat them. He says: "A lion is never afraid of a hundred sheep".

Nevertheless Shapur has to find weaknesses in the Roman army to defeat them. So he gives the army a weakness number.

In Shapur‘s opinion the weakness of an army is equal to the number of triplets i,?j,?k such that i?<?j?<?k and ai?>?aj?>?ak where ax is
the power of man standing at position x. The Roman army has one special trait — powers of all the people in it are distinct.

Help Shapur find out how weak the Romans are.

Input

The first line of input contains a single number n (3?≤?n?≤?106)
— the number of men in Roman army. Next line contains n different positive integers ai (1?≤?i?≤?n,?1?≤?ai?≤?109)
— powers of men in the Roman army.

Output

A single integer number, the weakness of the Roman army.

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cout (also
you may use %I64d).

Sample test(s)

input

3
3 2 1

output

1

input

3
2 3 1

output

0

input

4
10 8 3 1

output

4

input

4
1 5 4 3

output

1

题意是求 i<j<k && a[i]>a[j]>a[k] 的对数

如果只有2元组那就是求逆序数的做法

三元组的话就用一个树状数组x表示 数字i前面有多少个比自己大的个数

然后每次给这个y数组求和,再把x中>a[i]的个数存入y中即可

即使是4元也可以求了

#include <algorithm>
#include <cctype>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <climits>
#include <vector>
#include<iostream>
using namespace std;
#define ll long long
inline void rd(int &ret)
{
	char c;
	do { c = getchar();
	} while(c < '0' || c > '9');
	ret = c - '0';
	while((c=getchar()) >= '0' && c <= '9')
		ret = ret * 10 + ( c - '0' );
}
#define N 1000005
#define eps 1e-8
#define inf 1000000

ll n;
struct node{
	ll c[N];
	inline ll lowbit(ll x){return x&-x;}
	void init(){memset(c, 0, sizeof c);}
	ll sum(ll x){
		ll ans = 0;
		while(x<=n+10)
			ans += c[x], x+=lowbit(x);
		return ans;
	}
	void change(ll x, ll y){
		while(x)
			c[x] +=y, x-=lowbit(x);
	}
}x, y;
int haifei[1000000], panting[1000000];
int main()
{
	ll i, j;
	while(cin>>n)
	{
		ll ans = 0;
		for(i = 0; i < n; i++)rd(haifei[i]), panting[i] = haifei[i];
		x.init(); y.init();
		sort(haifei, haifei+n);
		for(i = 0; i < n; i++)
		{
			ll b = (lower_bound(haifei, haifei+n, panting[i]) - haifei) +1;

			ll siz = y.sum(b);
			ans += siz;
			y.change(b, x.sum(b));
			x.change(b, 1);
		}
		cout<<ans<<endl;
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 02:35:37

三元逆序对 求i<j<k && a[i]>a[j]>a[k] 的对数 树状数组Codeforces 61E Enemy is weak的相关文章

CodeForces 61E Enemy is weak 求i&lt;j&lt;k &amp;&amp; a[i]&gt;a[j]&gt;a[k] 的对数 树状数组

题目链接:点击打开链接 题意是求 i<j<k && a[i]>a[j]>a[k] 的对数 如果只有2元组那就是求逆序数的做法 三元组的话就用一个树状数组x表示 数字i前面有多少个比自己大的个数 然后每次给这个y数组求和,再把x中>a[i]的个数存入y中即可 #include <algorithm> #include <cctype> #include <cassert> #include <cstdio> #in

Codeforces 61E Enemy is weak 乞讨i&amp;lt;j&amp;lt;k &amp;amp;&amp;amp; a[i]&amp;gt;a[j]&amp;gt;a[k] 对数的 树阵

主题链接:点击打开链接 意大利正在寻求称号 i<j<k && a[i]>a[j]>a[k] 的对数 假设仅仅有2元组那就是求逆序数的做法 三元组的话就用一个树状数组x表示 数字i前面有多少个比自己大的个数 然后每次给这个y数组求和,再把x中>a[i]的个数存入y中就可以 #include <algorithm> #include <cctype> #include <cassert> #include <cstdio&

[luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】

传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直线按斜率从大到小排序后,第 k 条直线的斜率为多少. 为了避免精度误差,请输出斜率向下取整后的结果.(例如: ?1.5? = 1 , ??1.5? = ?2 ) 分析 一开始打了一个暴力,10分后来改着改着成了30分,浮点误差. 正解其实很简单,我们首先逆向思考一下,如果我们假设已经有了斜率k. 如

J - Association of Cats and Magical Lights Kattis - magicallights (树状数组+dfs序)

Rar the Cat((™)) is the founder of ACM (Association of Cats and Magical Lights). This is the story of the founding of ACM. It is the second half of the year again and Rar the Cat((™)) is looking forward to Christmas. When people think of Christmas, C

树状数组求逆序对:POJ 2299、3067

前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换相邻的两数使它有序,要你求出交换的次数.实质上就是求逆序对,网上有很多人说它的原理是冒泡排序,可以用归并排序来求出,但我一时间想不出它是如何和归并排序搭上边的(当初排序没学好啊~),只好用刚学过的树状数组来解决了.在POJ 1990中学到了如何在实际中应用上树状数组,没错,就是用个特殊的数组来记录即

POJ 2761 Feed the dogs(树状数组求区间第K大)

题目链接: 戳我 题目大意:Jiajia要为宠物狗,宠物狗按成一排站好(1 < i <= n),第 i 只狗的喜欢程度是 a[i], 之后他会先喂某个区间内第k个 即 n 个数, m个询问,接着是 n个数 接下来 m 行,每行是 l r k即 l 到 r 这个区间第 k 小的数,每个询问输出一个答案,即 a[i] 求区间第k大有很多算法, 详见此博客 [数据结构练习] 求区间第K大数的几种方法 我用的树状数组解法,来自 树状数组从前往后求和,用来解第k大(或小)的数 poj 2985 The

poj2299 Ultra-QuickSort 树状数组求逆序数

poj2299 Ultra-QuickSort   树状数组求逆序数 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 49587   Accepted: 18153 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequenc

【转载】【树状数组区间第K大/小】

原帖:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/15/1334109.html 回顾树状数组的定义,注意到有如下两条性质: 一,c[ans]=sum of A[ans-lowbit(ans)+1 ... ans];二,当ans=2^k时, c[ans]=sum of A[1 ... ans]; 下面说明findK(k)如何运作:1,设置边界条件ans,ans'<maxn且cnt<=k:2,初始化cnt=c[ans],其中ans=2^k且k

XJTUOJ wmq的队伍(树状数组求 K 元逆序对)

题目链接:http://oj.xjtuacm.com/problem/14/[分析]二元的逆序对应该都会求,可以用树状数组.这个题要求K元,我们可以看成二元的.我们先从后往前求二元逆序对数, 然后对于每一个数就可以求出在这个数后面的比他小的数的数量.然后我们再加一元时,当前扫到a[i],那么在树状数组中,对于那些比他大的数的 逆序对数+=上一元a[i]的逆序对数. #include <bits/stdc++.h> #define met(a,b) memset(a,b,sizeof a) #d