UVALive-4329 Ping pong (树状数组)

题目大意:有n个数排成一列,问从中能找出几个三元组(ai,aj,ak)满足i<j<k并且这三个数严格单调。

题目分析:枚举中间的数字aj,如果aj前面有c(j)个数a(j)小,后面有d(j)个数比a(j)小,那么aj为中间数时,共有c(j)*(n-j-d(j))+d(j)*(j-1-c(j))。定义x(i)表示 i 出现过几次,当枚举到aj 时,只需统计sum(x(1)~x(a(j)-1)便得c(j),d(j)求法类似。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<vector>
# include<queue>
# include<list>
# include<set>
# include<map>
# include<string>
# include<cmath>
# include<cstdlib>
# include<algorithm>
using namespace std;
# define LL long long

const int N=1005;
const int INF=1000000000;
const LL oo=0x7fffffffffffffff;
const double eps=1e-10;

int n;
int maxn;
int a[N*100];
int b[N*100];
int c[N*100];
int d[N*100];

int lowbit(int x)
{
	return (x&(-x));
}

int Query(int x)
{
	int res=0;
	while(x>0)
	{
		res+=b[x];
		x-=lowbit(x);
	}
	return res;
}

void Update(int x,int k)
{
	while(x<=maxn)
	{
		b[x]+=k;
		x+=lowbit(x);
	}
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		maxn=0;
		for(int i=1;i<=n;++i){
			scanf("%d",a+i);
			maxn=max(maxn,a[i]);
		}
		memset(b,0,sizeof(b));
		for(int i=1;i<=n;++i){
			c[i]=Query(a[i]-1);
			Update(a[i],1);
		}
		memset(b,0,sizeof(b));
		for(int i=n;i>=1;--i){
			d[i]=Query(a[i]-1);
			Update(a[i],1);
		}
		LL ans=0;
		for(int i=1;i<=n;++i){
			ans+=c[i]*(n-i-d[i]);
			ans+=d[i]*(i-1-c[i]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

  

时间: 2024-10-10 02:22:58

UVALive-4329 Ping pong (树状数组)的相关文章

UVALive 4329 Ping pong (树状数组)

白书上的例题.花了很多时间在找bug上,刚学树状数组,这道题add操作时要注意上限不是n. #include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 1e5 + 10; ll C[maxn]; ll n; inline ll lowbit(ll x) { return x & (-x); } ll sum(ll x) { ll ret = 0; while(x > 0) {

HDU 2492 Ping pong (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To improve their skill rank

uva 1428 - Ping pong(树状数组)

题目链接:uva 1428 - Ping pong 题目大意:一条大街上住着n个乒乓球爱好者,经常组织比赛.每个人都有一个不同的能力值,每场比赛需要3个人,裁判要住在两个选手之间,并且能力值也要在选手之间,问说最多能举行多少场比赛. 解题思路:预处理出bi和ci分别表示说在1~i中能力值比第i个人小的人和i+1~n中能力值比第i个人小的.处理过程用树状数组维护即可. #include <cstdio> #include <cstring> #include <algorith

poj3928 Ping pong 树状数组

http://poj.org/problem?id=3928 Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2087   Accepted: 798 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player

LA4329 Ping pong 树状数组

题意:一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术.每个人都有一个能力值a[i].每场比赛需要三个人:两名选手,一名裁判.他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两名选手之间.问一共能组织多少种比赛. 分析:考虑第i个人,假设a1到ai-1中有ci个比ai小,那么就有(i-1)-ci个比ai大:同理,如果ai+1到an中有di个比ai小,那么就有(n-i)-di个比ai大.i当裁判就有:ci * (n-i-di) + (i-1-ci)*di种比赛. 然后问题就

POJ 3928 Ping pong 树状数组模板题

开始用瓜神说的方法撸了一发线段树,早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #includ

POJ-3928 Ping pong(树状数组)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2985   Accepted: 1104 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To i

UVA1428 - Ping pong(树状数组)

题目链接 题目大意:有N个人,每个人都有一个技能值ai,现在要开展乒乓球比赛,要求要有两个选手和一个裁判,要求裁判需要在两名选手的中间而且技能值也是在两名选手的中间,问可以开展多少场比赛. 解题思路:对于第i个选手当裁判的话,设它前面位置的选手有ci个技能值比它低的,那么就有i - 1 - ci个比它高的,对于第i选手后面的位置,同样有di个技能值比它低的,那么就有N - i - di个比它高的.组合一下:ci?(N - i - di) + (i - 1 - ci) ? di.那么对于ci的值,

UVAlive - 4329 —— Ping pong 【树状数组】

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13895 #include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; const int MAXA = 100000 + 5; int n; int c[MAXA]; int sum(int i) { int

UVALive 4329 Ping pong(树状数组)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13895 题意:一条街上住有n个乒乓选手,每个人都有一个技能值,现在每场比赛需要3个人,两个选手,一个裁判:裁判须住在他们之间,且其技能值必须在两选手之间,求一共能组织多少种比赛. 注意到技能值的范围(1 ≤ ai ≤ 100000),所以我们可以树状数组(O(nlogn))处理得到一个ll数组,ll[x]表示住在x左边的并且技能值小于x的技能值的人数.类似逆着处理