小奇遐想

题目链接http://exam.upc.edu.cn/problem.php?cid=1390&pid=12

题目描述:

撷来一缕清风飘渺
方知今日书信未到
窗外三月天霁垂柳新长枝条
风中鸟啼犹带欢笑
——《清风醉梦》
小奇望着青天中的悠悠白云,开始了无限的遐想,在它的视野中,恰好有n朵高度不同的白云排成一排,他想从左到右选出四朵白云a,b,c,d,使得h_a<h_b<h_d<h_c,即看起来像是彩虹的形状!它想知道有多少种方案数。

输入

第一行包括1个整数n。
第二行包括n个整数,第i个正数表示h_i,保证这n个整数是n的一个全排列。

分析:

对于给出的一列数:可以先求出排序为  1  2  X X 的个数sum1,要保证:XX都要比第2个数大,且第1 个数,和第2 个数是递增的

然后求出排序为1 2 3 4 的个数sum2,其中 第1 ,2 ,3, 4个数都必须保证其为严格递增的。

 使用树状数组求逆序数即可。

然后sum1-sum2  即是所要求的  排序为1  2  4  3  的个数。

#include<stdio.h>
#include<string.h>
#define ll long long int
#define mode 16777216
ll a[200010],u[200010],v[200010];
ll maze[200010],ans[200010],n;
ll lowbit(ll x)
{
	return x&(-x);
}
void add(ll x,ll num)
{
	while(x<=n){
		maze[x]+=num;
		x+=lowbit(x);	
	}
}
ll summ(ll x)
{
	ll sum=0;
	while(x){
		sum+=maze[x];
		x-=lowbit(x);		
	}
	return sum;
}
void panadd(ll x,ll num)
{
	while(x<=n){
		ans[x]+=num;
		x+=lowbit(x);
	}
}
ll pansumm(ll x)
{
	ll sum=0;
	while(x){
		sum+=ans[x];
		x-=lowbit(x);
	}
	return sum;
}
int main()
{	
	int i;
	ll sum1,sum2;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		scanf("%lld",&a[i]);
		
	for(i = 1;i <= n;i++){
		u[i]=summ(a[i]);
		v[i]=a[i]-u[i]-1;
		add(a[i],1); 
	}
	
	sum1=0;
	for(i=1;i<=n;i++)
	   sum1= (sum1+u[i]*((n-i-v[i])*(n-i-v[i]-1)/2))%mode;//组合数,从大的数中任意选两个cn2
		
	sum2 =0;
	for(i=1;i<=n;i++){ 
		sum2 = (sum2+(pansumm(a[i])*(n-i-v[i]))%mode)%mode;
		panadd(a[i],u[i]);  // pansumm(a[i])表示a[i]的三个递增排序的个数
	}
	
	ll k=(sum1-sum2+mode)%mode;
	
	printf("%lld\n",k);
	 
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/dong_qian/article/details/81475226