【树状数组】Pascal山脉

【题目描述】

小卡卡顺着老者所指的方向,来到了Pascal神峰的顶峰。老者告诉小卡卡,Pascal山脉有很多座山,都排在一条直线上,每座山都有不同的高度。 
Pascal山的山顶有一个神奇的洞穴,进入这个洞穴后,你将会到达这座山前方的另一座山,更加神奇的是,你到达的山一定比他所在的山高度要小。而Pascal圣地最大的宝藏就藏在某一座Pascal山上的洞穴中,这个洞穴的特点是它有一道石门封闭着。 
小卡卡很想知道进入每座山的洞穴后,他所到达的不同的山会有多少种可能。

【输入格式】

第一行一个整数n,表示山的个数.(1<=n<=20000) 
第二行以后n行从前到后给出每座山的高度。另外两座山可以有相同的高度.(1<=每座山的高度<=maxlongint) 

【输出格式】

共n行,每行一个整数.第I行的整数表示他进入第I号山的洞穴后能够到达的不同的山的个数.


我们从前往后更新树状数组,后面的更小一定不会影响前面,山的高度过高,我们采用map映射

每次先查询所有比当前小的,在更新

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
using namespace std;
int n,a[20005],b[20005],cnt,tree[20005];
map<int,int> ma;
int sum(int x)
{
	int ans=0;
	while(x)
	{
		ans+=tree[x];
		x-=(x&-x);
	}
	return ans;
}
void add(int x)
{
	while(x<=cnt)
	{
		tree[x]++;
		x+=(x&-x);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
	{
		if(!ma[a[i]]) ma[a[i]]=++cnt;
	}
	for(int i=1;i<=n;i++)
	{
		int now=ma[b[i]];
		printf("%d\n",sum(now-1));
		add(now);
	}
}

猜你喜欢

转载自blog.csdn.net/Dy_Dream/article/details/82989874