hdu5775 树状数组

题意,有一个1~n的排列,用冒泡法排序,问整个过程中每个数字能达到的最左最右的位置绝对值之差。

思路:

  每个数能达到的最左位置不是开始位置就是排序完成后所在位置,所以L[ a[i] ] = min ( i , a[i] ),

  每个数能达到的最右位置为开始位置,或i+num,num为a[i]后小于a[i]的数字个数。那么num[i]怎么求呢?利用树状数组,

在输入第i个数后,sum[ a[i] ]表示a[i]之前小于等于a[i]的个数,而小于等于a[i]的个数一定有a[i]个,所以num=a[i]-sum[ a[i] ].

R[ a[i] ]= max ( i + a[i] - sum ( a[i] )  , a[i] );

太菜了,理了半天才理清。。

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>

using namespace std;

int t,n;
int a[100006];
int bit[100006];
int R[100006];
int L[100006];
	
void add(int i,int x){
	while(i<=n){
		bit[i]+=x;
		i+=i&-i;
	}
}

int sum(int i){
	int s=0;
	while(i>0){
		s+=bit[i];
		i-=i&-i;
	}
	return s;
}

int main(){
	freopen("in.txt","r",stdin);
	cin>>t;
	for(int ca=1;ca<=t;ca++){
		printf("Case #%d:",ca);
		cin>>n;
		memset(bit,0,sizeof(bit));
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			L[a[i]]=min(i,a[i]);
			add(a[i],1);
			R[a[i]]=max(i+a[i]-sum(a[i]),a[i]);
		}
		for(int i=1;i<=n;i++){
			printf(" %d",abs(L[i]-R[i]));
		}
		printf("\n");
	}
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值